INTO instruction #78

This commit is contained in:
simon987 2020-07-31 18:11:00 -04:00
parent b1d7121b22
commit 2ff19f24eb
5 changed files with 97 additions and 5 deletions

View File

@ -6,6 +6,7 @@ import net.simon987.mar.server.assembly.exception.CancelledException;
import net.simon987.mar.server.assembly.instruction.*;
import net.simon987.mar.server.event.CpuInitialisationEvent;
import net.simon987.mar.server.event.GameEvent;
import net.simon987.mar.server.game.GameUniverse;
import net.simon987.mar.server.game.objects.ControllableUnit;
import net.simon987.mar.server.game.objects.HardwareHost;
import net.simon987.mar.server.io.MongoSerializable;
@ -47,7 +48,7 @@ public class CPU implements MongoSerializable {
private int interruptVectorTableOffset;
private final int graceInstructionCount;
private int graceInstructionLeft;
private int graceInstructionsLeft;
private boolean isGracePeriod;
/**
@ -93,6 +94,7 @@ public class CPU implements MongoSerializable {
instructionSet.add(new JnaInstruction(this));
instructionSet.add(new JaInstruction(this));
instructionSet.add(new IntInstruction(this));
instructionSet.add(new IntoInstruction(this));
instructionSet.add(new IretInstruction(this));
}
@ -140,7 +142,7 @@ public class CPU implements MongoSerializable {
public void reset() {
status.clear();
ip = codeSectionOffset;
graceInstructionLeft = graceInstructionCount;
graceInstructionsLeft = graceInstructionCount;
isGracePeriod = false;
}
@ -157,13 +159,13 @@ public class CPU implements MongoSerializable {
counter++;
if (isGracePeriod) {
if (graceInstructionLeft-- == 0) {
if (graceInstructionsLeft-- == 0) {
writeExecutionStats(timeout, counter);
return timeout;
}
} else if (counter % 10000 == 0) {
if (System.currentTimeMillis() > (startTime + timeout)) {
interrupt(32);
interrupt(IntInstruction.INT_EXEC_LIMIT_REACHED);
isGracePeriod = true;
}
}

View File

@ -12,6 +12,10 @@ public class IntInstruction extends Instruction {
public static final int OPCODE = 48;
private final CPU cpu;
public static final int INT_DIVISION_BY_ZERO = 0;
public static final int INT_INTO_DETECTED_OVERFLOW = 4;
public static final int INT_EXEC_LIMIT_REACHED = 32;
public IntInstruction(CPU cpu) {
super("int", OPCODE);
this.cpu = cpu;

View File

@ -0,0 +1,38 @@
package net.simon987.mar.server.assembly.instruction;
import net.simon987.mar.server.assembly.*;
public class IntoInstruction extends Instruction {
public static final int OPCODE = 8;
private final CPU cpu;
public IntoInstruction(CPU cpu) {
super("into", OPCODE);
this.cpu = cpu;
}
@Override
public Status execute(Status status) {
if (status.isOverflowFlag()) {
cpu.interrupt(IntInstruction.INT_INTO_DETECTED_OVERFLOW);
}
return status;
}
@Override
public boolean noOperandsValid() {
return true;
}
@Override
public boolean operandsValid(Operand o1, Operand o2) {
return false;
}
@Override
public boolean operandValid(Operand o1) {
return false;
}
}

View File

@ -275,7 +275,7 @@ function parseInstruction(line, result, currentLine) {
if (new RegExp('\\b(?:mov|add|sub|and|or|test|cmp|shl|shr|mul|push|pop|div|xor|hwi|hwq|nop|neg|' +
'seta|setnbe|setae|setnb|setnc|setbe|setna|setb|setc|setnae|sete|setz|setne|setnz|setg|setnle|setge|setnl|setle|setng|setl|setnge|seto|setno|sets|setns|' +
'call|ret|jmp|jnz|jg|jl|jge|jle|int|jz|js|jns|brk|not|jc|jnc|ror|rol|sal|sar|jo|jno|inc|dec|rcl|xchg|rcr|pushf|popf|ja|jna)\\b').test(mnemonic.toLowerCase())) {
'call|ret|jmp|jnz|jg|jl|jge|jle|int|into|iret|jz|js|jns|brk|not|jc|jnc|ror|rol|sal|sar|jo|jno|inc|dec|rcl|xchg|rcr|pushf|popf|ja|jna)\\b').test(mnemonic.toLowerCase())) {
if (line.indexOf(",") !== -1) {

View File

@ -0,0 +1,48 @@
package net.simon987.mar.server.assembly.instruction;
import net.simon987.mar.server.TestExecutionResult;
import net.simon987.mar.server.assembly.TestHelper;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class IntoInstructionTest {
@Test
public void intoSimple1() {
String code = "" +
"isr: \n" +
" MOV X, 0x1234 \n" +
" IRET \n" +
".text \n" +
"MOV [4], isr \n" +
"INTO \n" +
"MOV Y, 0x4567 \n" +
"brk \n";
TestExecutionResult res = TestHelper.executeCode(code);
assertEquals(0, res.regValue("X"));
assertEquals(0x4567, res.regValue("Y"));
}
@Test
public void intoSimple2() {
String code = "" +
"isr: \n" +
" MOV X, 0x1234 \n" +
" IRET \n" +
".text \n" +
"MOV [4], isr \n" +
"MOV A, 0x7FFF \n" +
"ADD A, 1 \n" +
"INTO \n" +
"MOV Y, 0x4567 \n" +
"brk \n";
TestExecutionResult res = TestHelper.executeCode(code);
assertEquals(0x1234, res.regValue("X"));
assertEquals(0x4567, res.regValue("Y"));
}
}