package com.coderising.jvm.cmd;
import com.coderising.jvm.clz.ClassFile;
import com.coderising.jvm.engine.ExecutionResult;
import com.coderising.jvm.engine.JavaObject;
import com.coderising.jvm.engine.StackFrame;
public class ComparisonCmd extends TwoOperandCmd {
protected ComparisonCmd(ClassFile clzFile, String opCode) {
super(clzFile, opCode);
}
@Override
public void execute(StackFrame frame,ExecutionResult result) {
if(ByteCodeCommand.if_icmp_ge.equals(this.getOpCode())){
//注意次序
JavaObject jo2 = frame.getOprandStack().pop();
JavaObject jo1 = frame.getOprandStack().pop();
if(jo1.getIntValue() >= jo2.getIntValue()){
this.setJumpResult(result);
}
} else if(ByteCodeCommand.if_icmple.equals(this.getOpCode())){
//注意次序
JavaObject jo2 = frame.getOprandStack().pop();
JavaObject jo1 = frame.getOprandStack().pop();
if(jo1.getIntValue() <= jo2.getIntValue()){
this.setJumpResult(result);
}
} else if(ByteCodeCommand.goto_no_condition.equals(this.getOpCode())){
this.setJumpResult(result);
} else{
throw new RuntimeException(this.getOpCode() + "has not been implemented");
}
}
private int getOffsetFromStartCmd(){
//If the comparison succeeds, the unsigned branchbyte1 and branchbyte2
//are used to construct a signed 16-bit offset, where the offset is calculated
//to be (branchbyte1 << 8) | branchbyte2. Execution then proceeds at that
//offset from the address of the opcode of this if_icmp<cond> instruction
int index1 = this.getOprand1();
int index2 = this.getOprand2();
short offsetFromCurrent = (short)(index1 << 8 | index2);
return this.getOffset() + offsetFromCurrent ;
}
private void setJumpResult(ExecutionResult result){
int offsetFromStartCmd = this.getOffsetFromStartCmd();
result.setNextAction(ExecutionResult.JUMP);
result.setNextCmdOffset(offsetFromStartCmd);
}
@Override
public String toString() {
int index = this.getIndex();
String text = this.getReadableCodeText();
return this.getOffset()+":"+ this.getOpCode() + " "+text + " " + this.getOffsetFromStartCmd();
}
}