feat: 增加 64 位整数比较

This commit is contained in:
zhangxun 2025-06-16 22:37:44 +08:00 committed by Luke
parent a51502c622
commit 7bd795b796
14 changed files with 639 additions and 21 deletions

View File

@ -46,9 +46,9 @@ public class CmpJumpGenerator implements InstructionGenerator<IRCompareJumpInstr
// 获取右操作数所在的寄存器槽编号
int rightSlot = slotMap.get(ins.right());
// 加载左操作数到虚拟机栈
out.emit(OpHelper.opcode("I_LOAD") + " " + leftSlot);
out.emit(OpHelper.opcode("L_LOAD") + " " + leftSlot);
// 加载右操作数到虚拟机栈
out.emit(OpHelper.opcode("I_LOAD") + " " + rightSlot);
out.emit(OpHelper.opcode("L_LOAD") + " " + rightSlot);
// 获取与当前比较操作对应的虚拟机操作码
String cmpOp = IROpCodeMapper.toVMOp(ins.op());
// 生成分支跳转指令如果比较成立则跳转到目标标签

View File

@ -82,6 +82,7 @@ public final class IROpCodeMapper {
opcodeMap.put(IROpCode.NEG_D64, "D_NEG");
// 比较运算映射
// 整形32位比较运算映射
opcodeMap.put(IROpCode.CMP_EQ, "IC_E"); // 相等
opcodeMap.put(IROpCode.CMP_NE, "IC_NE"); // 不等
opcodeMap.put(IROpCode.CMP_LT, "IC_L"); // 小于
@ -89,6 +90,14 @@ public final class IROpCodeMapper {
opcodeMap.put(IROpCode.CMP_LE, "IC_LE"); // 小于等于
opcodeMap.put(IROpCode.CMP_GE, "IC_GE"); // 大于等于
// 整形64位比较运算映射
opcodeMap.put(IROpCode.CMP_LEQ, "LC_E"); // 相等
opcodeMap.put(IROpCode.CMP_LNE, "LC_NE"); // 不等
opcodeMap.put(IROpCode.CMP_LLT, "LC_L"); // 小于
opcodeMap.put(IROpCode.CMP_LGT, "LC_G"); // 大于
opcodeMap.put(IROpCode.CMP_LLE, "LC_LE"); // 小于等于
opcodeMap.put(IROpCode.CMP_LGE, "LC_GE"); // 大于等于
// 加载与存储
opcodeMap.put(IROpCode.LOAD, "I_LOAD"); // 加载
opcodeMap.put(IROpCode.STORE, "I_STORE"); // 存储

View File

@ -95,6 +95,12 @@ public final class OpHelper {
map.put("IC_GE", Integer.toString(VMOpCode.IC_GE));
map.put("IC_L", Integer.toString(VMOpCode.IC_L));
map.put("IC_LE", Integer.toString(VMOpCode.IC_LE));
map.put("LC_E", Integer.toString(VMOpCode.LC_E));
map.put("LC_NE", Integer.toString(VMOpCode.LC_NE));
map.put("LC_G", Integer.toString(VMOpCode.LC_G));
map.put("LC_GE", Integer.toString(VMOpCode.LC_GE));
map.put("LC_L", Integer.toString(VMOpCode.LC_L));
map.put("LC_LE", Integer.toString(VMOpCode.LC_LE));
map.put("I_PUSH", Integer.toString(VMOpCode.I_PUSH));
map.put("L_PUSH", Integer.toString(VMOpCode.L_PUSH));
map.put("S_PUSH", Integer.toString(VMOpCode.S_PUSH));

View File

@ -66,13 +66,21 @@ public enum IROpCode {
DIV_D64, // 64位浮点除法
NEG_D64, // 64位浮点取负
/* ───── 逻辑与比较运算指令 ───── */
CMP_EQ, // 相等比较a == b
CMP_NE, // 不等比较a != b
CMP_LT, // 小于比较a < b
CMP_GT, // 大于比较a > b
CMP_LE, // 小于等于a <= b
CMP_GE, // 大于等于a >= b
/* ───── 逻辑与比较运算指令32位整数int ───── */
CMP_EQ, // 32位相等比较a == b
CMP_NE, // 32位不等比较a != b
CMP_LT, // 32位小于比较a < b
CMP_GT, // 32位大于比较a > b
CMP_LE, // 32位小于等于a <= b
CMP_GE, // 32位大于等于a >= b
/* ───── 逻辑与比较运算指令64位整数long ───── */
CMP_LEQ, // 64位相等比较a == b
CMP_LNE, // 64位不等比较a != b
CMP_LLT, // 64位小于比较a < b
CMP_LGT, // 64位大于比较a > b
CMP_LLE, // 64位小于等于a <= b
CMP_LGE, // 64位大于等于a >= b
/* ───── 数据访问与常量操作 ───── */
LOAD, // 从内存加载数据至寄存器

View File

@ -40,11 +40,11 @@ public final class IROpCodeMappings {
);
// 比较操作符映射
public static final Map<String, IROpCode> CMP = Map.of(
"==", IROpCode.CMP_EQ,
"!=", IROpCode.CMP_NE,
"<", IROpCode.CMP_LT,
">", IROpCode.CMP_GT,
"<=", IROpCode.CMP_LE,
">=", IROpCode.CMP_GE
"==", IROpCode.CMP_LEQ,
"!=", IROpCode.CMP_LNE,
"<", IROpCode.CMP_LLT,
">", IROpCode.CMP_LGT,
"<=", IROpCode.CMP_LLE,
">=", IROpCode.CMP_LGE
);
}

View File

@ -9,12 +9,12 @@ import java.util.Map;
*/
public class IROpCodeUtils {
private static final Map<IROpCode, IROpCode> INVERT = Map.of(
IROpCode.CMP_EQ, IROpCode.CMP_NE,
IROpCode.CMP_NE, IROpCode.CMP_EQ,
IROpCode.CMP_LT, IROpCode.CMP_GE,
IROpCode.CMP_GE, IROpCode.CMP_LT,
IROpCode.CMP_GT, IROpCode.CMP_LE,
IROpCode.CMP_LE, IROpCode.CMP_GT
IROpCode.CMP_LEQ, IROpCode.CMP_LNE,
IROpCode.CMP_LNE, IROpCode.CMP_LEQ,
IROpCode.CMP_LLT, IROpCode.CMP_LGE,
IROpCode.CMP_LGE, IROpCode.CMP_LLT,
IROpCode.CMP_LGT, IROpCode.CMP_LLE,
IROpCode.CMP_LLE, IROpCode.CMP_LGT
);
/**

View File

@ -0,0 +1,76 @@
package org.jcnc.snow.vm.commands.control.long64;
import org.jcnc.snow.vm.interfaces.Command;
import org.jcnc.snow.vm.module.CallStack;
import org.jcnc.snow.vm.module.LocalVariableStore;
import org.jcnc.snow.vm.module.OperandStack;
import org.jcnc.snow.vm.utils.LoggingUtils;
/**
* The LCECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine.
* This class compares two values from the stack, and if they are equal, it jumps to the specified target command.
*
* <p>Specific behavior:</p>
* <ul>
* <li>Pops two integers from the virtual machine stack.</li>
* <li>If the two integers are equal, jumps to the target command.</li>
* <li>Otherwise, the program continues with the next command.</li>
* </ul>
*/
public class LCECommand implements Command {
/**
* Default constructor for creating an instance of LCECommand.
* This constructor is empty as no specific initialization is required.
*/
public LCECommand() {
// Empty constructor
}
/**
* Executes the virtual machine instruction's operation.
*
* <p>This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's
* specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction
* to be executed.</p>
*
* <p>The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow
* of execution by updating the program counter.</p>
*
* <p>The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching,
* function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame,
* while a `POP` instruction will remove an item from the operand stack.</p>
*
* @param parts The array of instruction parameters, which usually includes the operator and related arguments
* (such as target addresses, values, or function names). These parameters may vary based on
* the instruction being executed.
* @param currentPC The current program counter-value, indicating the address of the instruction being executed.
* This value is typically incremented after the execution of each instruction to point to the next one.
* @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack,
* such as pushing, popping, and peeking values.
* @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution.
* The store may not be used in every command but can be leveraged by instructions that require access
* to local variables.
* @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by
* instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions).
* @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the
* instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address
* corresponding to the target of the jump or the subroutine to call.
*/
@Override
public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) {
// Parse the target command address
int target = Integer.parseInt(parts[1]);
// Pop the two operands from the stack
long b = (long) operandStack.pop();
long a = (long) operandStack.pop();
// If the operands are equal, jump to the target command
if (a == b) {
LoggingUtils.logInfo("Jumping to command", String.valueOf(target));
return target;
}
return currentPC + 1;
}
}

View File

@ -0,0 +1,76 @@
package org.jcnc.snow.vm.commands.control.long64;
import org.jcnc.snow.vm.interfaces.Command;
import org.jcnc.snow.vm.module.CallStack;
import org.jcnc.snow.vm.module.LocalVariableStore;
import org.jcnc.snow.vm.module.OperandStack;
import org.jcnc.snow.vm.utils.LoggingUtils;
/**
* The LCGCommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine.
* This class compares two values from the stack, and if the first value is greater than the second, it jumps to the specified target command.
*
* <p>Specific behavior:</p>
* <ul>
* <li>Pops two integers from the virtual machine stack.</li>
* <li>If the first integer is greater than the second, jumps to the target command.</li>
* <li>Otherwise, the program continues with the next command.</li>
* </ul>
*/
public class LCGCommand implements Command {
/**
* Default constructor for creating an instance of LCGCommand.
* This constructor is empty as no specific initialization is required.
*/
public LCGCommand() {
// Empty constructor
}
/**
* Executes the virtual machine instruction's operation.
*
* <p>This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's
* specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction
* to be executed.</p>
*
* <p>The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow
* of execution by updating the program counter.</p>
*
* <p>The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching,
* function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame,
* while a `POP` instruction will remove an item from the operand stack.</p>
*
* @param parts The array of instruction parameters, which usually includes the operator and related arguments
* (such as target addresses, values, or function names). These parameters may vary based on
* the instruction being executed.
* @param currentPC The current program counter-value, indicating the address of the instruction being executed.
* This value is typically incremented after the execution of each instruction to point to the next one.
* @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack,
* such as pushing, popping, and peeking values.
* @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution.
* The store may not be used in every command but can be leveraged by instructions that require access
* to local variables.
* @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by
* instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions).
* @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the
* instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address
* corresponding to the target of the jump or the subroutine to call.
*/
@Override
public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) {
// Parse the target command address
int target = Integer.parseInt(parts[1]);
// Pop the two operands from the stack
long b = (long) operandStack.pop();
long a = (long) operandStack.pop();
// If the first operand is greater than the second, jump to the target command
if (a > b) {
LoggingUtils.logInfo("Jumping to command", String.valueOf(target));
return target;
}
return currentPC + 1;
}
}

View File

@ -0,0 +1,76 @@
package org.jcnc.snow.vm.commands.control.long64;
import org.jcnc.snow.vm.interfaces.Command;
import org.jcnc.snow.vm.module.CallStack;
import org.jcnc.snow.vm.module.LocalVariableStore;
import org.jcnc.snow.vm.module.OperandStack;
import org.jcnc.snow.vm.utils.LoggingUtils;
/**
* The LCGECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine.
* This class compares two values from the stack, and if the first value is greater than or equal to the second, it jumps to the specified target command.
*
* <p>Specific behavior:</p>
* <ul>
* <li>Pops two integers from the virtual machine stack.</li>
* <li>If the first integer is greater than or equal to the second, jumps to the target command.</li>
* <li>Otherwise, the program continues with the next command.</li>
* </ul>
*/
public class LCGECommand implements Command {
/**
* Default constructor for creating an instance of LCGECommand.
* This constructor is empty as no specific initialization is required.
*/
public LCGECommand() {
// Empty constructor
}
/**
* Executes the virtual machine instruction's operation.
*
* <p>This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's
* specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction
* to be executed.</p>
*
* <p>The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow
* of execution by updating the program counter.</p>
*
* <p>The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching,
* function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame,
* while a `POP` instruction will remove an item from the operand stack.</p>
*
* @param parts The array of instruction parameters, which usually includes the operator and related arguments
* (such as target addresses, values, or function names). These parameters may vary based on
* the instruction being executed.
* @param currentPC The current program counter-value, indicating the address of the instruction being executed.
* This value is typically incremented after the execution of each instruction to point to the next one.
* @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack,
* such as pushing, popping, and peeking values.
* @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution.
* The store may not be used in every command but can be leveraged by instructions that require access
* to local variables.
* @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by
* instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions).
* @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the
* instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address
* corresponding to the target of the jump or the subroutine to call.
*/
@Override
public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) {
// Parse the target command address
int target = Integer.parseInt(parts[1]);
// Pop the two operands from the stack
long b = (long) operandStack.pop();
long a = (long) operandStack.pop();
// If the first operand is greater than or equal to the second, jump to the target command
if (a >= b) {
LoggingUtils.logInfo("Jumping to command", String.valueOf(target));
return target;
}
return currentPC + 1;
}
}

View File

@ -0,0 +1,76 @@
package org.jcnc.snow.vm.commands.control.long64;
import org.jcnc.snow.vm.interfaces.Command;
import org.jcnc.snow.vm.module.CallStack;
import org.jcnc.snow.vm.module.LocalVariableStore;
import org.jcnc.snow.vm.module.OperandStack;
import org.jcnc.snow.vm.utils.LoggingUtils;
/**
* The LCLCommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine.
* This class compares two values from the stack, and if the first value is less than the second, it jumps to the specified target command.
*
* <p>Specific behavior:</p>
* <ul>
* <li>Pops two integers from the virtual machine stack.</li>
* <li>If the first integer is less than the second, jumps to the target command.</li>
* <li>Otherwise, the program continues with the next command.</li>
* </ul>
*/
public class LCLCommand implements Command {
/**
* Default constructor for creating an instance of LCLCommand.
* This constructor is empty as no specific initialization is required.
*/
public LCLCommand() {
// Empty constructor
}
/**
* Executes the virtual machine instruction's operation.
*
* <p>This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's
* specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction
* to be executed.</p>
*
* <p>The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow
* of execution by updating the program counter.</p>
*
* <p>The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching,
* function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame,
* while a `POP` instruction will remove an item from the operand stack.</p>
*
* @param parts The array of instruction parameters, which usually includes the operator and related arguments
* (such as target addresses, values, or function names). These parameters may vary based on
* the instruction being executed.
* @param currentPC The current program counter-value, indicating the address of the instruction being executed.
* This value is typically incremented after the execution of each instruction to point to the next one.
* @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack,
* such as pushing, popping, and peeking values.
* @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution.
* The store may not be used in every command but can be leveraged by instructions that require access
* to local variables.
* @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by
* instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions).
* @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the
* instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address
* corresponding to the target of the jump or the subroutine to call.
*/
@Override
public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) {
// Parse the target command address
int target = Integer.parseInt(parts[1]);
// Pop the two operands from the stack
long b = (long) operandStack.pop();
long a = (long) operandStack.pop();
// If the first operand is less than the second, jump to the target command
if (a < b) {
LoggingUtils.logInfo("Jumping to command", String.valueOf(target));
return target;
}
return currentPC + 1;
}
}

View File

@ -0,0 +1,76 @@
package org.jcnc.snow.vm.commands.control.long64;
import org.jcnc.snow.vm.interfaces.Command;
import org.jcnc.snow.vm.module.CallStack;
import org.jcnc.snow.vm.module.LocalVariableStore;
import org.jcnc.snow.vm.module.OperandStack;
import org.jcnc.snow.vm.utils.LoggingUtils;
/**
* The LCLECommand class implements the {@link Command} interface and represents a conditional jump command in the virtual machine.
* This class compares two values from the stack, and if the first value is less than or equal to the second, it jumps to the specified target command.
*
* <p>Specific behavior:</p>
* <ul>
* <li>Pops two integers from the virtual machine stack.</li>
* <li>If the first integer is less than or equal to the second, jumps to the target command.</li>
* <li>Otherwise, the program continues with the next command.</li>
* </ul>
*/
public class LCLECommand implements Command {
/**
* Default constructor for creating an instance of LCLECommand.
* This constructor is empty as no specific initialization is required.
*/
public LCLECommand() {
// Empty constructor
}
/**
* Executes the virtual machine instruction's operation.
*
* <p>This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's
* specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction
* to be executed.</p>
*
* <p>The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow
* of execution by updating the program counter.</p>
*
* <p>The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching,
* function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame,
* while a `POP` instruction will remove an item from the operand stack.</p>
*
* @param parts The array of instruction parameters, which usually includes the operator and related arguments
* (such as target addresses, values, or function names). These parameters may vary based on
* the instruction being executed.
* @param currentPC The current program counter-value, indicating the address of the instruction being executed.
* This value is typically incremented after the execution of each instruction to point to the next one.
* @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack,
* such as pushing, popping, and peeking values.
* @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution.
* The store may not be used in every command but can be leveraged by instructions that require access
* to local variables.
* @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by
* instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions).
* @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the
* instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address
* corresponding to the target of the jump or the subroutine to call.
*/
@Override
public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) {
// Parse the target command address
int target = Integer.parseInt(parts[1]);
// Pop the two operands from the stack
long b = (long) operandStack.pop();
long a = (long) operandStack.pop();
// If the first operand is less than or equal to the second, jump to the target command
if (a <= b) {
LoggingUtils.logInfo("Jumping to command", String.valueOf(target));
return target;
}
return currentPC + 1;
}
}

View File

@ -0,0 +1,76 @@
package org.jcnc.snow.vm.commands.control.long64;
import org.jcnc.snow.vm.interfaces.Command;
import org.jcnc.snow.vm.module.CallStack;
import org.jcnc.snow.vm.module.LocalVariableStore;
import org.jcnc.snow.vm.module.OperandStack;
import org.jcnc.snow.vm.utils.LoggingUtils;
/**
* The LCNECommand class implements the {@link Command} interface and represents a conditional jump command
* in the virtual machine that triggers if two values are not equal.
*
* <p>Specific behavior:</p>
* <ul>
* <li>Pops two integers from the virtual machine stack.</li>
* <li>If the two integers are not equal, jumps to the target command.</li>
* <li>Otherwise, the program continues with the next command.</li>
* </ul>
*/
public class LCNECommand implements Command {
/**
* Default constructor for creating an instance of LCNECommand.
* This constructor is empty as no specific initialization is required.
*/
public LCNECommand() {
// Empty constructor
}
/**
* Executes the virtual machine instruction's operation.
*
* <p>This method retrieves the necessary data from the virtual machine stack and local variable store based on the instruction's
* specific implementation, performs the operation, and updates the program counter (PC) to reflect the next instruction
* to be executed.</p>
*
* <p>The parameters provided allow the command to manipulate the operand stack, modify the local variables, and control the flow
* of execution by updating the program counter.</p>
*
* <p>The exact behavior of this method will depend on the specific instruction being executed (e.g., arithmetic, branching,
* function calls, etc.). For example, a `CALL` instruction will modify the call stack by pushing a new frame,
* while a `POP` instruction will remove an item from the operand stack.</p>
*
* @param parts The array of instruction parameters, which usually includes the operator and related arguments
* (such as target addresses, values, or function names). These parameters may vary based on
* the instruction being executed.
* @param currentPC The current program counter-value, indicating the address of the instruction being executed.
* This value is typically incremented after the execution of each instruction to point to the next one.
* @param operandStack The virtual machine's operand stack manager, responsible for performing operations on the operand stack,
* such as pushing, popping, and peeking values.
* @param localVariableStore The local variable store, typically used to manage method-local variables during instruction execution.
* The store may not be used in every command but can be leveraged by instructions that require access
* to local variables.
* @param callStack The virtual machine's call stack, which keeps track of the method invocation hierarchy. It is used by
* instructions that involve method calls or returns (such as `CALL` and `RETURN` instructions).
* @return The updated program counter-value, typically the current program counter-value incremented by 1, unless the
* instruction modifies control flow (such as a `JUMP` or `CALL`), in which case it may return a new address
* corresponding to the target of the jump or the subroutine to call.
*/
@Override
public int execute(String[] parts, int currentPC, OperandStack operandStack, LocalVariableStore localVariableStore, CallStack callStack) {
// Parse the target command address
int target = Integer.parseInt(parts[1]);
// Pop the two operands from the stack
long b = (long) operandStack.pop();
long a = (long) operandStack.pop();
// If the operands are not equal, jump to the target command
if (a != b) {
LoggingUtils.logInfo("Jumping to command", String.valueOf(target));
return target;
}
return currentPC + 1;
}
}

View File

@ -1101,6 +1101,7 @@ public class VMOpCode {
// 3. Control Flow Operations (91110)
// 3.1 JUMP (91-91)
/**
* JUMP Opcode: Represents an unconditional jump to a target instruction address.
* <p>This opcode is implemented by the {@link JumpCommand} class, which defines its specific execution logic.</p>
@ -1120,6 +1121,7 @@ public class VMOpCode {
* </ul>
*/
public static final int JUMP = 91;
// 3.2 int32 (92-97)
/**
* IC_E Opcode: Represents a conditional jump based on int32 equality.
* <p>This opcode is implemented by the {@link ICECommand} class, which defines its specific execution logic.</p>
@ -1246,6 +1248,133 @@ public class VMOpCode {
* </ul>
*/
public static final int IC_LE = 97;
// 3.3 long64 (98-103)
/**
* LC_E Opcode: Represents a conditional jump based on long64 equality.
* <p>This opcode is implemented by the {@link ICECommand} class, which defines its specific execution logic.</p>
*
* <p>Execution Steps:</p>
* <ol>
* <li>Parses the target instruction address from the instruction parameters.</li>
* <li>Pops two long64 values from the operand stack.</li>
* <li>Compares the two long64s for equality.</li>
* <li>If the long64s are equal, updates the program counter (PC) to the specified target address,
* effectively jumping to the target instruction.</li>
* <li>If the long64s are not equal, increments the program counter to proceed with the next sequential instruction.</li>
* </ol>
*
* <p>This opcode is commonly used for:</p>
* <ul>
* <li>Conditional branching in virtual machine execution based on long64 comparison.</li>
* <li>Implementing control flow structures such as if-statements and loops.</li>
* </ul>
*/
public static final int LC_E = 98;
/**
* LC_NE Opcode: Represents a conditional jump based on long64 inequality.
* <p>This opcode is implemented by the {@link ICNECommand} class, which defines its specific execution logic.</p>
*
* <p>Execution Steps:</p>
* <ol>
* <li>Parses the target instruction address from the instruction parameters.</li>
* <li>Pops two long64 values from the operand stack.</li>
* <li>Compares the two long64s for inequality.</li>
* <li>If the long64s are not equal, updates the program counter (PC) to the specified target address,
* effectively jumping to the target instruction.</li>
* <li>If the long64s are equal, increments the program counter to proceed with the next sequential instruction.</li>
* </ol>
*
* <p>This opcode is commonly used for:</p>
* <ul>
* <li>Conditional branching in virtual machine execution based on long64 comparison.</li>
* <li>Implementing control flow structures such as conditional loops and if-else statements.</li>
* </ul>
*/
public static final int LC_NE = 99;
/**
* LC_G Opcode: Represents a conditional jump based on long64 comparison (greater than).
* <p>This opcode is implemented by the {@link ICGCommand} class, which defines its specific execution logic.</p>
*
* <p>Execution Steps:</p>
* <ol>
* <li>Parses the target instruction address from the instruction parameters.</li>
* <li>Pops two long64 values from the operand stack.</li>
* <li>Compares the first long64 with the second to determine if it is greater.</li>
* <li>If the first long64 is greater than the second, updates the program counter (PC) to the specified target address,
* effectively jumping to the target instruction.</li>
* <li>If the first long64 is not greater than the second, increments the program counter to proceed with the next sequential instruction.</li>
* </ol>
*
* <p>This opcode is commonly used for:</p>
* <ul>
* <li>Conditional branching in virtual machine execution based on long64 comparison.</li>
* <li>Implementing control flow structures such as greater-than conditions in loops and conditional statements.</li>
* </ul>
*/
public static final int LC_G = 100;
/**
* LC_GE Opcode: Represents a conditional jump based on long64 comparison (greater than or equal to).
* <p>This opcode is implemented by the {@link ICGECommand} class, which defines its specific execution logic.</p>
*
* <p>Execution Steps:</p>
* <ol>
* <li>Parses the target instruction address from the instruction parameters.</li>
* <li>Pops two long64 values from the operand stack.</li>
* <li>Compares the first long64 with the second to determine if it is greater than or equal to the second long64.</li>
* <li>If the first long64 is greater than or equal to the second, updates the program counter (PC) to the specified target address,
* effectively jumping to the target instruction.</li>
* <li>If the first long64 is less than the second, increments the program counter to proceed with the next sequential instruction.</li>
* </ol>
*
* <p>This opcode is commonly used for:</p>
* <ul>
* <li>Conditional branching in virtual machine execution based on long64 comparison.</li>
* <li>Implementing control flow structures such as loops, conditional statements, and range checks.</li>
* </ul>
*/
public static final int LC_GE = 101;
/**
* LC_L Opcode: Represents a conditional jump based on long64 comparison (less than).
* <p>This opcode is implemented by the {@link ICLCommand} class, which defines its specific execution logic.</p>
*
* <p>Execution Steps:</p>
* <ol>
* <li>Parses the target instruction address from the instruction parameters.</li>
* <li>Pops two long64 values from the operand stack.</li>
* <li>Compares the first long64 with the second to determine if it is less than the second long64.</li>
* <li>If the first long64 is less than the second, updates the program counter (PC) to the specified target address,
* effectively jumping to the target instruction.</li>
* <li>If the first long64 is greater than or equal to the second, increments the program counter to proceed with the next sequential instruction.</li>
* </ol>
*
* <p>This opcode is commonly used for:</p>
* <ul>
* <li>Conditional branching in virtual machine execution based on long64 comparison.</li>
* <li>Implementing control flow structures such as loops, conditional statements, and range validations.</li>
* </ul>
*/
public static final int LC_L = 102;
/**
* LC_LE Opcode: Represents a conditional jump based on long64 comparison (less than or equal).
* <p>This opcode is implemented by the {@link ICLECommand} class, which defines its specific execution logic.</p>
*
* <p>Execution Steps:</p>
* <ol>
* <li>Parses the target instruction address from the instruction parameters.</li>
* <li>Pops two long64 values from the operand stack.</li>
* <li>Compares the first long64 with the second to determine if it is less than or equal to the second long64.</li>
* <li>If the first long64 is less than or equal to the second, updates the program counter (PC) to the specified target address,
* effectively jumping to the target instruction.</li>
* <li>If the first long64 is greater than the second, increments the program counter to proceed with the next sequential instruction.</li>
* </ol>
*
* <p>This opcode is commonly used for:</p>
* <ul>
* <li>Conditional branching in virtual machine execution based on long64 comparison.</li>
* <li>Implementing control flow structures such as loops, conditional statements, and boundary checks.</li>
* </ul>
*/
public static final int LC_LE = 103;
// 4. Stack Operations (111150)
// 4.1 PUSH (111-120)

View File

@ -16,6 +16,7 @@ import org.jcnc.snow.vm.commands.bitwise.long64.LOrCommand;
import org.jcnc.snow.vm.commands.bitwise.long64.LXorCommand;
import org.jcnc.snow.vm.commands.control.all.JumpCommand;
import org.jcnc.snow.vm.commands.control.int32.*;
import org.jcnc.snow.vm.commands.control.long64.*;
import org.jcnc.snow.vm.commands.function.CallCommand;
import org.jcnc.snow.vm.commands.function.RetCommand;
import org.jcnc.snow.vm.commands.memory.all.MovCommand;
@ -142,13 +143,22 @@ public class CommandFactory {
COMMANDS[VMOpCode.L_XOR] = new LXorCommand(); // 88
// 3. Control Flow Operations (91110)
// 3.1 JUMP (91-91)
COMMANDS[VMOpCode.JUMP] = new JumpCommand(); // 91
// 3.2 int32 (92-97)
COMMANDS[VMOpCode.IC_E] = new ICECommand(); // 92
COMMANDS[VMOpCode.IC_NE] = new ICNECommand(); // 93
COMMANDS[VMOpCode.IC_G] = new ICGCommand(); // 94
COMMANDS[VMOpCode.IC_GE] = new ICGECommand(); // 95
COMMANDS[VMOpCode.IC_L] = new ICLCommand(); // 96
COMMANDS[VMOpCode.IC_LE] = new ICLECommand(); // 97
// 3.3 long64 (98-103)
COMMANDS[VMOpCode.LC_E] = new LCECommand(); // 98
COMMANDS[VMOpCode.LC_NE] = new LCNECommand(); // 99
COMMANDS[VMOpCode.LC_G] = new LCGCommand(); // 100
COMMANDS[VMOpCode.LC_GE] = new LCGECommand(); // 101
COMMANDS[VMOpCode.LC_L] = new LCLCommand(); // 102
COMMANDS[VMOpCode.LC_LE] = new LCLECommand(); // 103
// 4. Stack Operations (111150)
// 4.1 PUSH (111-120)