diff --git a/src/com/gabongao/jvm/Interpreter.java b/src/com/gabongao/jvm/Interpreter.java new file mode 100644 index 0000000..1388e78 --- /dev/null +++ b/src/com/gabongao/jvm/Interpreter.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm; + +import com.gabongao.jvm.classfile.AttrCode; +import com.gabongao.jvm.classfile.AttributeInfo; +import com.gabongao.jvm.classfile.MemberInfo; +import com.gabongao.jvm.instructions.*; +import com.gabongao.jvm.rtda.Frame; +import com.gabongao.jvm.rtda.Thread; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/19. + */ +public class Interpreter { + public void doInterpreter(MemberInfo memberInfo) { + AttrCode codeAttr = memberInfo.getCodeAttribure(); + int maxLocals = codeAttr.getMaxLocals(); + int maxStack = codeAttr.getMaxStack(); + byte[] byteCode = codeAttr.getCode(); + Thread thread = new Thread(); + Frame frame = new Frame(thread, maxLocals, maxStack); + thread.pushFrame(frame); + try { + loop(thread, byteCode); + } catch (Exception e) { + e.printStackTrace(); + System.out.println(); + System.out.printf("LocalVars: %s\n", frame.getLocalVars()); + System.out.printf("OperandStack: %s\n", frame.getOperandStack()); + } + } + + public void loop(Thread thread, byte[] byteCode) { + Frame frame = thread.popFrame(); + BytecodeReader bytecodeReader = new BytecodeReader(); + int n = 1; + for (; ; ) { + int pc = frame.getNextPc(); + thread.setPc(pc); + System.out.printf("loop: %2d\t", n); + bytecodeReader.reset(byteCode, pc); + char opcode = (char) bytecodeReader.readInt8(); + Instruction instruction = Factory.newInstruction((byte) opcode); + instruction.fetchOperands(bytecodeReader); + if (n == 13 || n == 14) { + System.out.printf("%d\t", bytecodeReader.getPc()); + } + frame.setNextPc(bytecodeReader.getPc()); + System.out.printf("pc:%2d\t inst:%s\n", pc, instruction.getClass().getName()); + instruction.execute(frame); + n++; + } + } + + +} diff --git a/src/com/gabongao/jvm/Jvm.java b/src/com/gabongao/jvm/Jvm.java index c8eaf5d..7255208 100644 --- a/src/com/gabongao/jvm/Jvm.java +++ b/src/com/gabongao/jvm/Jvm.java @@ -1,14 +1,12 @@ package com.gabongao.jvm; import com.gabongao.jvm.classfile.ClassFile; +import com.gabongao.jvm.classfile.MemberInfo; import com.gabongao.jvm.classpath.ClassPath; import com.gabongao.jvm.rtda.Frame; import com.gabongao.jvm.rtda.LocalVars; import com.gabongao.jvm.rtda.OperandStack; -import java.io.File; -import java.util.Arrays; - /** *         ┏┓   ┏┓+ + *        ┏┛┻━━━┛┻┓ + + @@ -97,12 +95,41 @@ public class Jvm { } */ - + /* ch04 Frame frame = new Frame(100, 100); testLocalVars(frame.getLocalVars()); testOperandStack(frame.getOperandStack()); + */ + Interpreter interpreter = new Interpreter(); + ClassPath cp = new ClassPath(); + cp.parse(cmd.jreOption, cmd.cpOption); + String className = cmd.className.replace(".", "/").concat(".class"); + ClassFile classFile = loadClass(className, cp); + classFile.read(); + MemberInfo mainMethod = getMainMethod(classFile); + if (mainMethod != null) { + interpreter.doInterpreter(mainMethod); + } else { + System.out.printf("Main method not found in class %s\n", className); + } + } + public static MemberInfo getMainMethod(ClassFile classFile) { + for (MemberInfo methodInfo : classFile.getMethods() + ) { + if ("main".equals(methodInfo.getName()) && methodInfo.getDescriptor().equals("([Ljava/lang/String;)V")) { + return methodInfo; + } + } + return null; + } + + + public static ClassFile loadClass(String className, ClassPath classPath) { + byte[] classData = classPath.readClass(className); + return new ClassFile(classData); + } private static void testLocalVars(LocalVars localVars) { localVars.setInt(0, 100); diff --git a/src/com/gabongao/jvm/classfile/AttrCode.java b/src/com/gabongao/jvm/classfile/AttrCode.java index 9889a4a..f6198da 100644 --- a/src/com/gabongao/jvm/classfile/AttrCode.java +++ b/src/com/gabongao/jvm/classfile/AttrCode.java @@ -33,11 +33,11 @@ package com.gabongao.jvm.classfile; * Created by Imgaojp on 2017/2/18. */ public class AttrCode implements AttributeInfo { - char maxStack, maxLocals; byte[] code; - ConstantPool constantPool; - AttributeInfo[] attributes; - ExceptionTableEntry[] exceptionTableEntries; + private char maxStack, maxLocals; + private ConstantPool constantPool; + private AttributeInfo[] attributes; + private ExceptionTableEntry[] exceptionTableEntries; public AttrCode(ConstantPool constantPool) { @@ -54,6 +54,30 @@ public class AttrCode implements AttributeInfo { attributes = ClassFile.readAttributes(classReader, constantPool); } + public char getMaxStack() { + return maxStack; + } + + public char getMaxLocals() { + return maxLocals; + } + + public byte[] getCode() { + return code; + } + + public ConstantPool getConstantPool() { + return constantPool; + } + + public AttributeInfo[] getAttributes() { + return attributes; + } + + public ExceptionTableEntry[] getExceptionTableEntries() { + return exceptionTableEntries; + } + public ExceptionTableEntry[] readExceptionTable(ClassReader classReader) { char exceptionTableLength = classReader.readUint16(); ExceptionTableEntry[] exceptionTableEntries = new ExceptionTableEntry[exceptionTableLength]; diff --git a/src/com/gabongao/jvm/classfile/MemberInfo.java b/src/com/gabongao/jvm/classfile/MemberInfo.java index f79fab5..8fe958c 100644 --- a/src/com/gabongao/jvm/classfile/MemberInfo.java +++ b/src/com/gabongao/jvm/classfile/MemberInfo.java @@ -33,9 +33,9 @@ package com.gabongao.jvm.classfile; * Created by Imgaojp on 2017/2/18. */ public class MemberInfo { - ConstantPool cp; - char accessFlags, nameIndex, descriptorIndex; - AttributeInfo[] attributes; + private ConstantPool cp; + private char accessFlags, nameIndex, descriptorIndex; + private AttributeInfo[] attributes; public MemberInfo(ClassReader classReader, ConstantPool cp) { @@ -46,6 +46,16 @@ public class MemberInfo { this.attributes = ClassFile.readAttributes(classReader, cp); } + public AttrCode getCodeAttribure() { + for (AttributeInfo attr : attributes + ) { + if (attr instanceof AttrCode) { + return (AttrCode) attr; + } + } + return null; + } + public String getName() { return cp.getUTF8(nameIndex); } diff --git a/src/com/gabongao/jvm/instructions/BranchInstruction.java b/src/com/gabongao/jvm/instructions/BranchInstruction.java new file mode 100644 index 0000000..fedb2c2 --- /dev/null +++ b/src/com/gabongao/jvm/instructions/BranchInstruction.java @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm.instructions; + +import com.gabongao.jvm.rtda.Frame; +import com.gabongao.jvm.rtda.Object; +import com.gabongao.jvm.rtda.OperandStack; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/18. + */ +public class BranchInstruction implements Instruction { + private int offset; + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + offset = bytecodeReader.readInt16(); + } + + @Override + public void execute(Frame frame) { + } + + ; + + public void branch(Frame frame, int offset) { + int pc = frame.getThread().getPc(); + int nextPc = pc + offset; + frame.setNextPc(nextPc); + } + + public class Ifeq extends BranchInstruction { + @Override + public void execute(Frame frame) { + int val = frame.getOperandStack().popInt(); + if (val == 0) { + branch(frame, super.offset); + } + } + } + + public class Ifne extends BranchInstruction { + @Override + public void execute(Frame frame) { + int val = frame.getOperandStack().popInt(); + if (val != 0) { + branch(frame, super.offset); + } + } + } + + public class Iflt extends BranchInstruction { + @Override + public void execute(Frame frame) { + int val = frame.getOperandStack().popInt(); + if (val < 0) { + branch(frame, super.offset); + } + } + } + + public class Ifle extends BranchInstruction { + @Override + public void execute(Frame frame) { + int val = frame.getOperandStack().popInt(); + if (val <= 0) { + branch(frame, super.offset); + } + } + } + + public class Ifgt extends BranchInstruction { + @Override + public void execute(Frame frame) { + int val = frame.getOperandStack().popInt(); + if (val > 0) { + branch(frame, super.offset); + } + } + } + + public class Ifge extends BranchInstruction { + @Override + public void execute(Frame frame) { + int val = frame.getOperandStack().popInt(); + if (val >= 0) { + branch(frame, super.offset); + } + } + } + + public class If_icmpne extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int val2 = operandStack.popInt(); + int val1 = operandStack.popInt(); + if (val1 != val2) { + branch(frame, super.offset); + } + } + } + + public class If_icmpeq extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int val2 = operandStack.popInt(); + int val1 = operandStack.popInt(); + if (val1 == val2) { + branch(frame, super.offset); + } + } + } + + public class If_icmplt extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int val2 = operandStack.popInt(); + int val1 = operandStack.popInt(); + if (val1 < val2) { + branch(frame, super.offset); + } + } + } + + public class If_icmple extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int val2 = operandStack.popInt(); + int val1 = operandStack.popInt(); + if (val1 <= val2) { + branch(frame, super.offset); + } + } + } + + public class If_icmpgt extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int val2 = operandStack.popInt(); + int val1 = operandStack.popInt(); + if (val1 > val2) { + branch(frame, super.offset); + } + } + } + + public class If_icmpge extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int val2 = operandStack.popInt(); + int val1 = operandStack.popInt(); + if (val1 >= val2) { + branch(frame, super.offset); + } + } + } + + public class If_acmpeq extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Object val2 = operandStack.popRef(); + Object val1 = operandStack.popRef(); + if (val1 == val2) { + branch(frame, super.offset); + } + } + } + + public class If_acmpne extends BranchInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Object val2 = operandStack.popRef(); + Object val1 = operandStack.popRef(); + if (val1 != val2) { + branch(frame, super.offset); + } + } + } + + public class Goto extends BranchInstruction { + @Override + public void execute(Frame frame) { + branch(frame, super.offset); + } + } + + public class Goto_W extends BranchInstruction { + @Override + public void execute(Frame frame) { + branch(frame, super.offset); + } + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.offset = bytecodeReader.readInt32(); + } + } + + public class TableSwitch extends BranchInstruction { + int low, high, defaultOffset; + int[] jumpOffsets; + + @Override + public void execute(Frame frame) { + int index = frame.getOperandStack().popInt(); + int offset; + if ((index >= low) && (index <= high)) { + offset = (jumpOffsets[index - low]); + } else { + offset = defaultOffset; + } + branch(frame, offset); + } + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + bytecodeReader.skipPadding(); + defaultOffset = bytecodeReader.readInt32(); + low = bytecodeReader.readInt32(); + high = bytecodeReader.readInt32(); + int jumpOffsetsCount = high - low + 1; + jumpOffsets = bytecodeReader.readInt32s(jumpOffsetsCount); + } + } + + public class LookUpSwitch extends BranchInstruction { + int defaultOffset, npairs; + int[] matchOffsets; + + @Override + public void execute(Frame frame) { + int key = frame.getOperandStack().popInt(); + for (int i = 0; i < npairs * 2; i += 2) { + if (matchOffsets[i] == key) { + branch(frame, matchOffsets[i + 1]); + return; + } + } + branch(frame, defaultOffset); + } + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + bytecodeReader.skipPadding(); + defaultOffset = bytecodeReader.readInt32(); + npairs = bytecodeReader.readInt32(); + matchOffsets = bytecodeReader.readInt32s(npairs * 2); + } + } + + public class Ifnull extends BranchInstruction { + @Override + public void execute(Frame frame) { + Object ref = frame.getOperandStack().popRef(); + if (ref == null) { + branch(frame, super.offset); + } + } + } + + public class Ifnonnull extends BranchInstruction { + @Override + public void execute(Frame frame) { + Object ref = frame.getOperandStack().popRef(); + if (ref != null) { + branch(frame, super.offset); + } + } + } +} diff --git a/src/com/gabongao/jvm/instructions/BytecodeReader.java b/src/com/gabongao/jvm/instructions/BytecodeReader.java new file mode 100644 index 0000000..232244d --- /dev/null +++ b/src/com/gabongao/jvm/instructions/BytecodeReader.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm.instructions; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/18. + */ +public class BytecodeReader { + private byte[] code; + private int pc; + + public void reset(byte[] code, int pc) { + this.code = code; + this.pc = pc; + } + + public int getPc() { + return pc; + } + + public char readUint8() { + byte b = code[pc]; + pc++; + return (char) b; + } + + public char readUint16() { +// Byte.toUnsignedInt((byte) readUint8()); + char high = (char) (readUint8() << 8); + char low = readUint8(); + char res = (char) ((high & 0xff00) | (low & 0x00ff)); + return res; + } + + public int readInt8() { + return (int) readUint8(); + } + + public int readInt16() { + char uint16 = readUint16(); + if (uint16 >> 15 == 1) { + return (((~(uint16 - 1)) & 0x000000007f) * -1); + } else { + return uint16; + } + } + + public int readInt32() { + return (((((int) readUint8()) << 24) & 0xff000000) | ((((int) readUint8()) << 16) & 0x00ff0000) | ((((int) readUint8()) << 8) & 0x0000ff00) | ((((int) readUint8())) & 0x000000ff)); + } + + public void skipPadding() { + while ((pc % 4) != 0) { + readInt8(); + } + } + + public int[] readInt32s(int count) { + int[] ints = new int[count]; + for (int i = 0; i < count; i++) { + ints[i] = readInt32(); + } + return ints; + } +} diff --git a/src/com/gabongao/jvm/instructions/Factory.java b/src/com/gabongao/jvm/instructions/Factory.java new file mode 100644 index 0000000..0b4cee6 --- /dev/null +++ b/src/com/gabongao/jvm/instructions/Factory.java @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm.instructions; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/19. + */ +public class Factory { + + static OperandsInstruction operandsInstruction = new OperandsInstruction(); + static BranchInstruction branchInstruction = new BranchInstruction(); + static Index8Instruction index8Instruction = new Index8Instruction(); + + public static Instruction newInstruction(byte opcode) { + switch (Byte.toUnsignedInt(opcode)) { + case 0x00: + return operandsInstruction.new Nop(); + case 0x01: + return operandsInstruction.new Aconst_null(); + case 0x02: + return operandsInstruction.new Iconst_M1(); + case 0x03: + return operandsInstruction.new Iconst_0(); + case 0x04: + return operandsInstruction.new Iconst_1(); + case 0x05: + return operandsInstruction.new Iconst_2(); + case 0x06: + return operandsInstruction.new Iconst_3(); + case 0x07: + return operandsInstruction.new Iconst_4(); + case 0x08: + return operandsInstruction.new Iconst_5(); + case 0x09: + return operandsInstruction.new Lconst_0(); + case 0x0a: + return operandsInstruction.new Lconst_1(); + case 0x0b: + return operandsInstruction.new Fconst_0(); + case 0x0c: + return operandsInstruction.new Fconst_1(); + case 0x0d: + return operandsInstruction.new Fconst_2(); + case 0x0e: + return operandsInstruction.new Dconst_0(); + case 0x0f: + return operandsInstruction.new Dconst_1(); + case 0x10: + return operandsInstruction.new Bipush(); + case 0x11: + return operandsInstruction.new Sipush(); + //case 0x12: + // return &LDC{} + //case 0x13: + // return &LDC_W{} + //case 0x14: + // return &LDC2_W{} + case 0x15: + return index8Instruction.new Iload(); + case 0x16: + return index8Instruction.new Lload(); + case 0x17: + return index8Instruction.new Fload(); + case 0x18: + return index8Instruction.new Dload(); + case 0x19: + return index8Instruction.new Aload(); + case 0x1a: + return (index8Instruction.new Iload()).new Iload_0(); + case 0x1b: + return (index8Instruction.new Iload()).new Iload_1(); + case 0x1c: + return (index8Instruction.new Iload()).new Iload_2(); + case 0x1d: + return (index8Instruction.new Iload()).new Iload_3(); + case 0x1e: + return (index8Instruction.new Lload()).new Lload_0(); + case 0x1f: + return (index8Instruction.new Lload()).new Lload_1(); + case 0x20: + return (index8Instruction.new Lload()).new Lload_2(); + case 0x21: + return (index8Instruction.new Lload()).new Lload_3(); + case 0x22: + return (index8Instruction.new Fload()).new Fload_0(); + case 0x23: + return (index8Instruction.new Fload()).new Fload_1(); + case 0x24: + return (index8Instruction.new Fload()).new Fload_2(); + case 0x25: + return (index8Instruction.new Fload()).new Fload_3(); + case 0x26: + return (index8Instruction.new Dload()).new Dload_0(); + case 0x27: + return (index8Instruction.new Dload()).new Dload_1(); + case 0x28: + return (index8Instruction.new Dload()).new Dload_2(); + case 0x29: + return (index8Instruction.new Dload()).new Dload_3(); + case 0x2a: + return (index8Instruction.new Aload()).new Aload_0(); + case 0x2b: + return (index8Instruction.new Aload()).new Aload_1(); + case 0x2c: + return (index8Instruction.new Aload()).new Aload_2(); + case 0x2d: + return (index8Instruction.new Aload()).new Aload_3(); + //case 0x2e: + // return iaload + //case 0x2f: + // return laload + //case 0x30: + // return faload + //case 0x31: + // return daload + //case 0x32: + // return aaload + //case 0x33: + // return baload + //case 0x34: + // return caload + //case 0x35: + // return saload + case 0x36: + return index8Instruction.new Istore(); + case 0x37: + return index8Instruction.new Lstore(); + + case 0x38: + return index8Instruction.new Fstore(); + + case 0x39: + return index8Instruction.new Dstore(); + + case 0x3a: + return index8Instruction.new Astore(); + + case 0x3b: + return (index8Instruction.new Istore()).new Istore_0(); + case 0x3c: + return (index8Instruction.new Istore()).new Istore_1(); + case 0x3d: + return (index8Instruction.new Istore()).new Istore_2(); + case 0x3e: + return (index8Instruction.new Istore()).new Istore_3(); + case 0x3f: + return (index8Instruction.new Lstore()).new Lstore_0(); + case 0x40: + return (index8Instruction.new Lstore()).new Lstore_1(); + case 0x41: + return (index8Instruction.new Lstore()).new Lstore_2(); + case 0x42: + return (index8Instruction.new Lstore()).new Lstore_3(); + case 0x43: + return (index8Instruction.new Fstore()).new Fstore_0(); + case 0x44: + return (index8Instruction.new Fstore()).new Fstore_1(); + case 0x45: + return (index8Instruction.new Fstore()).new Fstore_2(); + case 0x46: + return (index8Instruction.new Fstore()).new Fstore_3(); + case 0x47: + return (index8Instruction.new Dstore()).new Dstore_0(); + case 0x48: + return (index8Instruction.new Dstore()).new Dstore_1(); + case 0x49: + return (index8Instruction.new Dstore()).new Dstore_2(); + case 0x4a: + return (index8Instruction.new Dstore()).new Dstore_3(); + case 0x4b: + return (index8Instruction.new Astore()).new Astore_0(); + case 0x4c: + return (index8Instruction.new Astore()).new Astore_1(); + case 0x4d: + return (index8Instruction.new Astore()).new Astore_2(); + case 0x4e: + return (index8Instruction.new Astore()).new Astore_3(); + //case 0x4f: + // return iastore + //case 0x50: + // return lastore + //case 0x51: + // return fastore + //case 0x52: + // return dastore + //case 0x53: + // return aastore + //case 0x54: + // return bastore + //case 0x55: + // return castore + //case 0x56: + // return sastore + case 0x57: + return operandsInstruction.new Pop(); + case 0x58: + return operandsInstruction.new Pop2(); + case 0x59: + return operandsInstruction.new Dup(); + case 0x5a: + return operandsInstruction.new Dup_X1(); + case 0x5b: + return operandsInstruction.new Dup_X2(); + case 0x5c: + return operandsInstruction.new Dup2(); + case 0x5d: + return operandsInstruction.new Dup2_X1(); + case 0x5e: + return operandsInstruction.new Dup2_X2(); + case 0x5f: + return operandsInstruction.new Swap(); + case 0x60: + return operandsInstruction.new Iadd(); + case 0x61: + return operandsInstruction.new Ladd(); + case 0x62: + return operandsInstruction.new Fadd(); + case 0x63: + return operandsInstruction.new Dadd(); + case 0x64: + return operandsInstruction.new Isub(); + case 0x65: + return operandsInstruction.new Lsub(); + case 0x66: + return operandsInstruction.new Fsub(); + case 0x67: + return operandsInstruction.new Dsub(); + case 0x68: + return operandsInstruction.new Imul(); + case 0x69: + return operandsInstruction.new Lmul(); + case 0x6a: + return operandsInstruction.new Fmul(); + case 0x6b: + return operandsInstruction.new Dmul(); + case 0x6c: + return operandsInstruction.new Idiv(); + case 0x6d: + return operandsInstruction.new Ldiv(); + case 0x6e: + return operandsInstruction.new Fdiv(); + case 0x6f: + return operandsInstruction.new Ddiv(); + case 0x70: + return operandsInstruction.new Irem(); + case 0x71: + return operandsInstruction.new Lrem(); + case 0x72: + return operandsInstruction.new Frem(); + case 0x73: + return operandsInstruction.new Drem(); + case 0x74: + return operandsInstruction.new Ineg(); + case 0x75: + return operandsInstruction.new Lneg(); + case 0x76: + return operandsInstruction.new Fneg(); + case 0x77: + return operandsInstruction.new Dneg(); + case 0x78: + return operandsInstruction.new Ishl(); + case 0x79: + return operandsInstruction.new Lshl(); + case 0x7a: + return operandsInstruction.new Ishr(); + case 0x7b: + return operandsInstruction.new Lshr(); + case 0x7c: + return operandsInstruction.new Iushr(); + case 0x7d: + return operandsInstruction.new Lushr(); + case 0x7e: + return operandsInstruction.new Iand(); + case 0x7f: + return operandsInstruction.new Land(); + case 0x80: + return operandsInstruction.new Ior(); + case 0x81: + return operandsInstruction.new Lor(); + case 0x82: + return operandsInstruction.new Ixor(); + case 0x83: + return operandsInstruction.new Lxor(); + case 0x84: + return index8Instruction.new Iinc(); + case 0x85: + return operandsInstruction.new I2l(); + case 0x86: + return operandsInstruction.new I2f(); + case 0x87: + return operandsInstruction.new I2d(); + case 0x88: + return operandsInstruction.new L2i(); + case 0x89: + return operandsInstruction.new L2f(); + case 0x8a: + return operandsInstruction.new L2d(); + case 0x8b: + return operandsInstruction.new F2i(); + case 0x8c: + return operandsInstruction.new F2l(); + case 0x8d: + return operandsInstruction.new F2d(); + case 0x8e: + return operandsInstruction.new D2i(); + case 0x8f: + return operandsInstruction.new D2l(); + case 0x90: + return operandsInstruction.new D2f(); +// case 0x91: +// return operandsInstruction.new I2b(); +// case 0x92: +// return i2c +// case 0x93: +// return i2s + case 0x94: + return operandsInstruction.new Lcmp(); + case 0x95: + return (operandsInstruction.new Fcmp()).new Fcmpl(); + case 0x96: + return (operandsInstruction.new Fcmp()).new Fcmpg(); + case 0x97: + return (operandsInstruction.new Dcmp()).new Dcmpl(); + case 0x98: + return (operandsInstruction.new Dcmp()).new Dcmpg(); + case 0x99: + return branchInstruction.new Ifeq(); + case 0x9a: + return branchInstruction.new Ifne(); + case 0x9b: + return branchInstruction.new Iflt(); + case 0x9c: + return branchInstruction.new Ifge(); + case 0x9d: + return branchInstruction.new Ifgt(); + case 0x9e: + return branchInstruction.new Ifle(); + case 0x9f: + return branchInstruction.new If_icmpeq(); + case 0xa0: + return branchInstruction.new If_icmpne(); + case 0xa1: + return branchInstruction.new If_icmplt(); + case 0xa2: + return branchInstruction.new If_icmpge(); + case 0xa3: + return branchInstruction.new If_icmpgt(); + case 0xa4: + return branchInstruction.new If_icmple(); + case 0xa5: + return branchInstruction.new If_acmpeq(); + case 0xa6: + return branchInstruction.new If_acmpne(); + case 0xa7: + return branchInstruction.new Goto(); +// case 0xa8: +// return &control.JSR { +// } +// case 0xa9: +// return &control.RET { +// } + case 0xaa: + return branchInstruction.new TableSwitch(); + case 0xab: + return branchInstruction.new LookUpSwitch(); +// +// case 0xac: +// return ireturn +// case 0xad: +// return lreturn +// case 0xae: +// return freturn +// case 0xaf: +// return dreturn +// case 0xb0: +// return areturn +// case 0xb1: +// return _return + //case 0xb2: + // return &GET_STATIC{} + //case 0xb3: + // return &PUT_STATIC{} + //case 0xb4: + // return &GET_FIELD{} + //case 0xb5: + // return &PUT_FIELD{} + //case 0xb6: + // return &INVOKE_VIRTUAL{} + //case 0xb7: + // return &INVOKE_SPECIAL{} + //case 0xb8: + // return &INVOKE_STATIC{} + //case 0xb9: + // return &INVOKE_INTERFACE{} + //case 0xba: + // return &INVOKE_DYNAMIC{} + //case 0xbb: + // return &NEW{} + //case 0xbc: + // return &NEW_ARRAY{} + //case 0xbd: + // return &ANEW_ARRAY{} + //case 0xbe: + // return arraylength + //case 0xbf: + // return athrow + //case 0xc0: + // return &CHECK_CAST{} + //case 0xc1: + // return &INSTANCE_OF{} + //case 0xc2: + // return monitorenter + //case 0xc3: + // return monitorexit +// case 0xc4: +// return &extended.WIDE { +// } + //case 0xc5: + // return &MULTI_ANEW_ARRAY{} + case 0xc6: + return branchInstruction.new Ifnull(); + case 0xc7: + return branchInstruction.new Ifnonnull(); + case 0xc8: + return branchInstruction.new Goto_W(); +// case 0xc9: +// return &control.JSR_W { +// } + ////case 0xca: todo breakpoint + //case 0xfe: + // return invoke_native // impdep1 + //case 0xff: + // return &BOOTSTRAP{} // impdep2 + default: + throw new RuntimeException(String.format("Bad opcode: 0X%X", opcode)); + } + + } +} diff --git a/src/com/gabongao/jvm/instructions/Index16Instruction.java b/src/com/gabongao/jvm/instructions/Index16Instruction.java new file mode 100644 index 0000000..c6d4fef --- /dev/null +++ b/src/com/gabongao/jvm/instructions/Index16Instruction.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm.instructions; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/18. + */ +public abstract class Index16Instruction implements Instruction { + private char Index; + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + Index = bytecodeReader.readUint16(); + } +} diff --git a/src/com/gabongao/jvm/instructions/Index8Instruction.java b/src/com/gabongao/jvm/instructions/Index8Instruction.java new file mode 100644 index 0000000..37a9f93 --- /dev/null +++ b/src/com/gabongao/jvm/instructions/Index8Instruction.java @@ -0,0 +1,688 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm.instructions; + +import com.gabongao.jvm.rtda.Frame; +import com.gabongao.jvm.rtda.LocalVars; +import com.gabongao.jvm.rtda.Object; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/18. + */ +public class Index8Instruction implements Instruction { + private char Index; + + public char getIndex() { + return Index; + } + + public void setIndex(char index) { + Index = index; + } + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + Index = bytecodeReader.readUint8(); + } + + public void execute(Frame frame) { + } + + ; + + public class Iload extends Index8Instruction { + @Override + public void execute(Frame frame) { + _iload(frame, getIndex()); + } + + public void _iload(Frame frame, int index) { + int val = frame.getLocalVars().getInt(index); + frame.getOperandStack().pushInt(val); + } + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + public class Iload_0 extends Iload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _iload(frame, 0); + } + } + + public class Iload_1 extends Iload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _iload(frame, 1); + } + } + + public class Iload_2 extends Iload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _iload(frame, 2); + } + } + + public class Iload_3 extends Iload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _iload(frame, 3); + } + } + + } + + public class Aload extends Index8Instruction { + @Override + public void execute(Frame frame) { + _aload(frame, getIndex()); + } + + public void _aload(Frame frame, int index) { + Object val = frame.getLocalVars().getRef(index); + frame.getOperandStack().pushRef(val); + } + + + public class Aload_0 extends Aload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _aload(frame, 0); + } + } + + public class Aload_1 extends Aload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _aload(frame, 1); + } + } + + public class Aload_2 extends Aload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _aload(frame, 2); + } + } + + public class Aload_3 extends Aload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _aload(frame, 3); + } + } + } + + public class Dload extends Index8Instruction { + @Override + public void execute(Frame frame) { + _dload(frame, getIndex()); + } + + public void _dload(Frame frame, int index) { + double val = frame.getLocalVars().getDouble(index); + frame.getOperandStack().pushDouble(val); + } + + public class Dload_0 extends Dload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dload(frame, 0); + } + } + + public class Dload_1 extends Dload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dload(frame, 1); + } + } + + public class Dload_2 extends Dload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dload(frame, 2); + } + } + + public class Dload_3 extends Dload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dload(frame, 3); + } + } + + } + + public class Fload extends Index8Instruction { + @Override + public void execute(Frame frame) { + _fload(frame, getIndex()); + } + + public void _fload(Frame frame, int index) { + float val = frame.getLocalVars().getFloat(index); + frame.getOperandStack().pushFloat(val); + } + + public class Fload_0 extends Fload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fload(frame, 0); + } + } + + public class Fload_1 extends Fload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fload(frame, 1); + } + } + + public class Fload_2 extends Fload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fload(frame, 2); + } + } + + public class Fload_3 extends Fload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fload(frame, 3); + } + } + + } + + public class Lload extends Index8Instruction { + @Override + public void execute(Frame frame) { + _lload(frame, getIndex()); + } + + public void _lload(Frame frame, int index) { + long val = frame.getLocalVars().getLong(index); + frame.getOperandStack().pushLong(val); + } + + public class Lload_0 extends Lload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lload(frame, 0); + } + } + + public class Lload_1 extends Lload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lload(frame, 1); + } + } + + public class Lload_2 extends Lload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lload(frame, 2); + } + } + + public class Lload_3 extends Lload { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lload(frame, 3); + } + } + + } + + public class Lstore extends Index8Instruction { + @Override + public void execute(Frame frame) { + _lstore(frame, getIndex()); + } + + public void _lstore(Frame frame, int index) { + Long val = frame.getOperandStack().popLong(); + frame.getLocalVars().setLong(index, val); + } + + public class Lstore_0 extends Lstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lstore(frame, 0); + } + } + + public class Lstore_1 extends Lstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lstore(frame, 1); + } + } + + public class Lstore_2 extends Lstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lstore(frame, 2); + } + } + + public class Lstore_3 extends Lstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _lstore(frame, 3); + } + } + + } + + public class Astore extends Index8Instruction { + @Override + public void execute(Frame frame) { + _astore(frame, getIndex()); + } + + public void _astore(Frame frame, int index) { + Object val = frame.getOperandStack().popRef(); + frame.getLocalVars().setRef(index, val); + } + + public class Astore_0 extends Astore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _astore(frame, 0); + } + } + + public class Astore_1 extends Astore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _astore(frame, 1); + } + } + + public class Astore_2 extends Astore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _astore(frame, 2); + } + } + + public class Astore_3 extends Astore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _astore(frame, 3); + } + } + + } + + public class Istore extends Index8Instruction { + @Override + public void execute(Frame frame) { + _istore(frame, getIndex()); + } + + public void _istore(Frame frame, int index) { + int val = frame.getOperandStack().popInt(); + frame.getLocalVars().setInt(index, val); + } + + public class Istore_0 extends Istore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _istore(frame, 0); + } + } + + public class Istore_1 extends Istore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _istore(frame, 1); + } + } + + public class Istore_2 extends Istore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _istore(frame, 2); + } + } + + public class Istore_3 extends Istore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _istore(frame, 3); + } + } + + } + + public class Dstore extends Index8Instruction { + @Override + public void execute(Frame frame) { + _dstore(frame, getIndex()); + } + + public void _dstore(Frame frame, int index) { + double val = frame.getOperandStack().popDouble(); + frame.getLocalVars().setDouble(index, val); + } + + public class Dstore_0 extends Dstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dstore(frame, 0); + } + } + + public class Dstore_1 extends Dstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dstore(frame, 1); + } + } + + public class Dstore_2 extends Dstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dstore(frame, 2); + } + } + + public class Dstore_3 extends Dstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _dstore(frame, 3); + } + } + } + + public class Fstore extends Index8Instruction { + @Override + public void execute(Frame frame) { + _fstore(frame, getIndex()); + } + + public void _fstore(Frame frame, int index) { + float val = frame.getOperandStack().popFloat(); + frame.getLocalVars().setFloat(index, val); + } + + public class Fstore_0 extends Fstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fstore(frame, 0); + } + } + + public class Fstore_1 extends Fstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fstore(frame, 1); + } + } + + public class Fstore_2 extends Fstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fstore(frame, 2); + } + } + + public class Fstore_3 extends Fstore { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + + } + + @Override + public void execute(Frame frame) { + _fstore(frame, 3); + } + } + } + + public class Iinc extends Index8Instruction { + private int constVal; + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.setIndex(bytecodeReader.readUint8()); + constVal = bytecodeReader.readInt8(); + } + + @Override + public void execute(Frame frame) { + LocalVars localVars = frame.getLocalVars(); + localVars.setInt(super.getIndex(), localVars.getInt(super.getIndex()) + constVal); + } + } +} \ No newline at end of file diff --git a/src/com/gabongao/jvm/instructions/Instruction.java b/src/com/gabongao/jvm/instructions/Instruction.java new file mode 100644 index 0000000..7267131 --- /dev/null +++ b/src/com/gabongao/jvm/instructions/Instruction.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm.instructions; + +import com.gabongao.jvm.rtda.Frame; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/18. + */ +public interface Instruction { + void fetchOperands(BytecodeReader bytecodeReader); + + void execute(Frame frame); +} diff --git a/src/com/gabongao/jvm/instructions/OperandsInstruction.java b/src/com/gabongao/jvm/instructions/OperandsInstruction.java new file mode 100644 index 0000000..36d55c7 --- /dev/null +++ b/src/com/gabongao/jvm/instructions/OperandsInstruction.java @@ -0,0 +1,950 @@ +/* + * Copyright (c) 2017. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.gabongao.jvm.instructions; + +import com.gabongao.jvm.rtda.Frame; +import com.gabongao.jvm.rtda.OperandStack; +import com.gabongao.jvm.rtda.Slot; +import com.gabongao.jvm.rtda.Stack; +import org.ietf.jgss.Oid; +import sun.awt.OSInfo; + +/** + *         ┏┓   ┏┓+ + + *        ┏┛┻━━━┛┻┓ + + + *        ┃       ┃ + *        ┃   ━   ┃ ++ + + + + *        ████━████ ┃+ + *        ┃       ┃ + + *        ┃   ┻   ┃ + *        ┃       ┃ + + + *        ┗━┓   ┏━┛ + *          ┃   ┃ + *          ┃   ┃ + + + + + *          ┃   ┃    Code is far away from bug with the animal protecting + *          ┃   ┃ +     神兽保佑,代码无bug + *          ┃   ┃ + *          ┃   ┃  + + *          ┃    ┗━━━┓ + + + *          ┃        ┣┓ + *          ┃        ┏┛ + *          ┗┓┓┏━┳┓┏┛ + + + + + *           ┃┫┫ ┃┫┫ + *           ┗┻┛ ┗┻┛+ + + + + * Created by Imgaojp on 2017/2/18. + */ +public class OperandsInstruction implements Instruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + //TODO + } + + public void execute(Frame frame) { + } + + ; + + public class Nop extends OperandsInstruction { + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + + } + } + + public class Aconst_null extends OperandsInstruction { + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushRef(null); + } + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + } + + public class Dconst_0 extends OperandsInstruction { + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushDouble(0.0); + } + } + + public class Dconst_1 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushDouble(1.0); + } + } + + public class Fconst_0 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushFloat(0.0f); + } + } + + public class Fconst_1 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushFloat(1.0f); + } + } + + public class Fconst_2 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushDouble(2.0f); + } + } + + public class Iconst_M1 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt(-1); + } + } + + public class Iconst_0 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt(0); + } + } + + public class Iconst_1 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt(1); + } + } + + public class Iconst_2 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt(2); + } + } + + public class Iconst_3 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt(3); + } + } + + public class Iconst_4 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt(4); + } + } + + public class Iconst_5 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt(5); + } + } + + public class Lconst_0 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushLong(0L); + } + } + + public class Lconst_1 extends OperandsInstruction { + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + super.fetchOperands(bytecodeReader); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushLong(1L); + } + } + + public class Bipush extends OperandsInstruction { + byte val; + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + val = (byte) bytecodeReader.readUint8(); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt((int) val); + } + } + + public class Sipush extends OperandsInstruction { + char val; + + @Override + public void fetchOperands(BytecodeReader bytecodeReader) { + val = bytecodeReader.readUint16(); + } + + @Override + public void execute(Frame frame) { + frame.getOperandStack().pushInt((int) val); + } + } + + public class Pop extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + operandStack.popSlot(); + } + } + + public class Pop2 extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + operandStack.popSlot(); + operandStack.popSlot(); + } + } + + public class Dup extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Slot slot = operandStack.popSlot(); + operandStack.pushSlot(slot); + operandStack.pushSlot(slot); + } + } + + public class Dup_X1 extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Slot slot1 = operandStack.popSlot(); + Slot slot2 = operandStack.popSlot(); + operandStack.pushSlot(slot1); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + } + } + + public class Dup_X2 extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Slot slot1 = operandStack.popSlot(); + Slot slot2 = operandStack.popSlot(); + Slot slot3 = operandStack.popSlot(); + operandStack.pushSlot(slot1); + operandStack.pushSlot(slot3); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + } + } + + public class Dup2 extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Slot slot1 = operandStack.popSlot(); + Slot slot2 = operandStack.popSlot(); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + } + } + + public class Dup2_X1 extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Slot slot1 = operandStack.popSlot(); + Slot slot2 = operandStack.popSlot(); + Slot slot3 = operandStack.popSlot(); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + operandStack.pushSlot(slot3); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + } + } + + public class Dup2_X2 extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Slot slot1 = operandStack.popSlot(); + Slot slot2 = operandStack.popSlot(); + Slot slot3 = operandStack.popSlot(); + Slot slot4 = operandStack.popSlot(); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + operandStack.pushSlot(slot4); + operandStack.pushSlot(slot3); + operandStack.pushSlot(slot2); + operandStack.pushSlot(slot1); + } + } + + public class Swap extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + Slot slot1 = operandStack.popSlot(); + Slot slot2 = operandStack.popSlot(); + operandStack.pushSlot(slot1); + operandStack.pushSlot(slot2); + } + } + + public class Irem extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + int v2 = stack.popInt(); + int v1 = stack.popInt(); + if (v2 == 0) { + throw new RuntimeException("ArithmeticException"); + } + stack.pushInt(v1 % v2); + } + } + + public class Lrem extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + long v2 = stack.popLong(); + long v1 = stack.popLong(); + if (v2 == 0) { + throw new RuntimeException("ArithmeticException"); + } + stack.pushLong(v1 % v2); + } + } + + public class Frem extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + float v2 = stack.popFloat(); + float v1 = stack.popFloat(); + stack.pushFloat(v1 % v2); + } + } + + public class Drem extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + double v2 = stack.popDouble(); + double v1 = stack.popDouble(); + stack.pushDouble(v1 % v2); + } + } + + public class Idiv extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + int v2 = stack.popInt(); + int v1 = stack.popInt(); + if (v2 == 0) { + throw new RuntimeException("ArithmeticException"); + } + stack.pushInt(v1 / v2); + } + } + + public class Ldiv extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + long v2 = stack.popLong(); + long v1 = stack.popLong(); + if (v2 == 0) { + throw new RuntimeException("ArithmeticException"); + } + stack.pushLong(v1 / v2); + } + } + + public class Fdiv extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + float v2 = stack.popFloat(); + float v1 = stack.popFloat(); + stack.pushFloat(v1 / v2); + } + } + + public class Ddiv extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack stack = frame.getOperandStack(); + double v2 = stack.popDouble(); + double v1 = stack.popDouble(); + stack.pushDouble(v1 / v2); + } + } + + public class Iadd extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 + v2); + } + } + + public class Dadd extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + double v2 = operandStack.popDouble(); + double v1 = operandStack.popDouble(); + operandStack.pushDouble(v1 + v2); + } + } + + public class Fadd extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + float v2 = operandStack.popFloat(); + float v1 = operandStack.popFloat(); + operandStack.pushFloat(v1 + v2); + } + } + + public class Ladd extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long v2 = operandStack.popLong(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 + v2); + } + } + + public class Isub extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 - v2); + } + } + + public class Dsub extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + double v2 = operandStack.popDouble(); + double v1 = operandStack.popDouble(); + operandStack.pushDouble(v1 - v2); + } + } + + public class Fsub extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + float v2 = operandStack.popFloat(); + float v1 = operandStack.popFloat(); + operandStack.pushFloat(v1 - v2); + } + } + + public class Lsub extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long v2 = operandStack.popLong(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 - v2); + } + } + + public class Imul extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 * v2); + } + } + + public class Dmul extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + double v2 = operandStack.popDouble(); + double v1 = operandStack.popDouble(); + operandStack.pushDouble(v1 * v2); + } + } + + public class Fmul extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + float v2 = operandStack.popFloat(); + float v1 = operandStack.popFloat(); + operandStack.pushFloat(v1 * v2); + } + } + + public class Lmul extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long v2 = operandStack.popLong(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 * v2); + } + } + + public class Ineg extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int val = operandStack.popInt(); + operandStack.pushInt(-val); + } + } + + public class Dneg extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + double val = operandStack.popDouble(); + operandStack.pushDouble(-val); + } + } + + public class Fneg extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + float val = operandStack.popFloat(); + operandStack.pushFloat(-val); + } + } + + public class Lneg extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long val = operandStack.popLong(); + operandStack.pushLong(-val); + } + } + + public class Ishl extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 << v2); + } + } + + public class Ishr extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 >> v2); + } + } + + public class Iushr extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 >>> v2); + } + } + + public class Lshl extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 << v2); + } + } + + public class Lshr extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 >> v2); + } + } + + public class Lushr extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 >>> v2); + } + } + + public class Iand extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 & v2); + } + } + + public class Land extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long v2 = operandStack.popLong(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 & v2); + } + } + + public class Ior extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 | v2); + } + } + + public class Lor extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long v2 = operandStack.popLong(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 | v2); + } + } + + public class Ixor extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int v2 = operandStack.popInt(); + int v1 = operandStack.popInt(); + operandStack.pushInt(v1 ^ v2); + } + } + + public class Lxor extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long v2 = operandStack.popLong(); + long v1 = operandStack.popLong(); + operandStack.pushLong(v1 ^ v2); + } + } + + public class D2f extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + double d = operandStack.popDouble(); + operandStack.pushFloat((float) d); + } + } + + public class D2i extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + double d = operandStack.popDouble(); + operandStack.pushInt((int) d); + } + } + + public class D2l extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + double d = operandStack.popDouble(); + operandStack.pushLong((long) d); + } + } + + public class I2f extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int i = operandStack.popInt(); + operandStack.pushFloat((float) i); + } + } + + public class I2d extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int i = operandStack.popInt(); + operandStack.pushDouble((double) i); + } + } + + public class I2l extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + int i = operandStack.popInt(); + operandStack.pushLong((long) i); + } + } + + public class F2i extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + float f = operandStack.popFloat(); + operandStack.pushInt((int) f); + } + } + + public class F2d extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + float f = operandStack.popFloat(); + operandStack.pushDouble((double) f); + } + } + + public class F2l extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + float f = operandStack.popFloat(); + operandStack.pushLong((long) f); + } + } + + public class L2i extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long l = operandStack.popLong(); + operandStack.pushInt((int) l); + } + } + + public class L2d extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long l = operandStack.popLong(); + operandStack.pushDouble((double) l); + } + } + + public class L2f extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long l = operandStack.popLong(); + operandStack.pushFloat((float) l); + } + } + + public class Lcmp extends OperandsInstruction { + @Override + public void execute(Frame frame) { + OperandStack operandStack = frame.getOperandStack(); + long v2 = operandStack.popLong(); + long v1 = operandStack.popLong(); + if (v1 > v2) { + operandStack.pushInt(1); + } else if (v1 == v2) { + operandStack.pushInt(0); + } else { + operandStack.pushInt(-1); + } + } + } + + public class Fcmp extends OperandsInstruction { + @Override + public void execute(Frame frame) { + } + + public void _fcmp(Frame frame, boolean gFlag) { + OperandStack operandStack = frame.getOperandStack(); + float v2 = operandStack.popFloat(); + float v1 = operandStack.popFloat(); + if (v1 > v2) { + operandStack.pushInt(1); + } else if (v1 == v2) { + operandStack.pushInt(0); + } else if (v1 < v2) { + operandStack.pushInt(-1); + } else if (gFlag) { + operandStack.pushInt(1); + } else { + operandStack.pushInt(-1); + } + } + + public class Fcmpg extends Fcmp { + @Override + public void execute(Frame frame) { + _fcmp(frame, true); + } + } + + public class Fcmpl extends Fcmp { + @Override + public void execute(Frame frame) { + _fcmp(frame, false); + } + } + } + + public class Dcmp extends OperandsInstruction { + @Override + public void execute(Frame frame) { + } + + public void _dcmp(Frame frame, boolean gFlag) { + OperandStack operandStack = frame.getOperandStack(); + double v2 = operandStack.popDouble(); + double v1 = operandStack.popDouble(); + if (v1 > v2) { + operandStack.pushInt(1); + } else if (v1 == v2) { + operandStack.pushInt(0); + } else if (v1 < v2) { + operandStack.pushInt(-1); + } else if (gFlag) { + operandStack.pushInt(1); + } else { + operandStack.pushInt(-1); + } + } + + public class Dcmpg extends Dcmp { + @Override + public void execute(Frame frame) { + _dcmp(frame, true); + } + } + + public class Dcmpl extends Dcmp { + @Override + public void execute(Frame frame) { + _dcmp(frame, false); + } + } + } + +} diff --git a/src/com/gabongao/jvm/rtda/Frame.java b/src/com/gabongao/jvm/rtda/Frame.java index bab7e66..69f267d 100644 --- a/src/com/gabongao/jvm/rtda/Frame.java +++ b/src/com/gabongao/jvm/rtda/Frame.java @@ -36,8 +36,11 @@ public class Frame { private Frame lower; private LocalVars localVars; private OperandStack operandStack; + private Thread thread; + private int nextPc; - public Frame(int maxLocals, int maxStack) { + public Frame(Thread thread, int maxLocals, int maxStack) { + this.thread = thread; localVars = new LocalVars(maxLocals); operandStack = new OperandStack(maxStack); } @@ -46,6 +49,18 @@ public class Frame { return localVars; } + public Thread getThread() { + return thread; + } + + public int getNextPc() { + return nextPc; + } + + public void setNextPc(int nextPc) { + this.nextPc = nextPc; + } + public OperandStack getOperandStack() { return operandStack; } diff --git a/src/com/gabongao/jvm/rtda/LocalVars.java b/src/com/gabongao/jvm/rtda/LocalVars.java index 11bf944..98b71fc 100644 --- a/src/com/gabongao/jvm/rtda/LocalVars.java +++ b/src/com/gabongao/jvm/rtda/LocalVars.java @@ -8,6 +8,8 @@ package com.gabongao.jvm.rtda; +import java.util.Arrays; + /** *         ┏┓   ┏┓+ + *        ┏┛┻━━━┛┻┓ + + @@ -90,4 +92,9 @@ public class LocalVars { public double getDouble(int index) { return Double.longBitsToDouble(getLong(index)); } + + @Override + public String toString() { + return "slots:" + Arrays.asList(slots).toString(); + } } diff --git a/src/com/gabongao/jvm/rtda/OperandStack.java b/src/com/gabongao/jvm/rtda/OperandStack.java index 8b0225d..9cc3d94 100644 --- a/src/com/gabongao/jvm/rtda/OperandStack.java +++ b/src/com/gabongao/jvm/rtda/OperandStack.java @@ -8,6 +8,8 @@ package com.gabongao.jvm.rtda; +import java.util.Arrays; + /** *         ┏┓   ┏┓+ + *        ┏┛┻━━━┛┻┓ + + @@ -44,6 +46,14 @@ public class OperandStack { } } + @Override + public String toString() { + return "OperandStack{" + + "size=" + size + + ", slots=" + Arrays.toString(slots) + + '}'; + } + public void pushInt(int val) { slots[size] = new Slot(); slots[size].setNum(val); @@ -102,4 +112,14 @@ public class OperandStack { public double popDouble() { return Double.longBitsToDouble(popLong()); } + + public void pushSlot(Slot slot) { + slots[size] = slot; + size++; + } + + public Slot popSlot() { + size--; + return slots[size]; + } } diff --git a/src/com/gabongao/jvm/rtda/Slot.java b/src/com/gabongao/jvm/rtda/Slot.java index 69f769b..b902612 100644 --- a/src/com/gabongao/jvm/rtda/Slot.java +++ b/src/com/gabongao/jvm/rtda/Slot.java @@ -36,6 +36,14 @@ public class Slot { private int num; private Object ref; + @Override + public String toString() { + return "Slot{" + + "num=" + num + + ", ref=" + ref + + '}'; + } + public int getNum() { return num; } diff --git a/src/com/gabongao/jvm/rtda/Thread.java b/src/com/gabongao/jvm/rtda/Thread.java index 9abfe0a..8542668 100644 --- a/src/com/gabongao/jvm/rtda/Thread.java +++ b/src/com/gabongao/jvm/rtda/Thread.java @@ -59,4 +59,5 @@ public class Thread { public Frame currentFrame() { return stack.top(); } + }