From 2ff19f24eb107c74300d145ed1657ea7f174c9e5 Mon Sep 17 00:00:00 2001 From: simon987 Date: Fri, 31 Jul 2020 18:11:00 -0400 Subject: [PATCH] INTO instruction #78 --- .../net/simon987/mar/server/assembly/CPU.java | 10 ++-- .../assembly/instruction/IntInstruction.java | 4 ++ .../assembly/instruction/IntoInstruction.java | 38 +++++++++++++++ src/main/resources/static/js/editor.js | 2 +- .../instruction/IntoInstructionTest.java | 48 +++++++++++++++++++ 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 src/main/java/net/simon987/mar/server/assembly/instruction/IntoInstruction.java create mode 100644 src/test/java/net/simon987/mar/server/assembly/instruction/IntoInstructionTest.java diff --git a/src/main/java/net/simon987/mar/server/assembly/CPU.java b/src/main/java/net/simon987/mar/server/assembly/CPU.java index 8db31f9..50894f8 100755 --- a/src/main/java/net/simon987/mar/server/assembly/CPU.java +++ b/src/main/java/net/simon987/mar/server/assembly/CPU.java @@ -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; } } diff --git a/src/main/java/net/simon987/mar/server/assembly/instruction/IntInstruction.java b/src/main/java/net/simon987/mar/server/assembly/instruction/IntInstruction.java index 1fb9303..e185bfb 100644 --- a/src/main/java/net/simon987/mar/server/assembly/instruction/IntInstruction.java +++ b/src/main/java/net/simon987/mar/server/assembly/instruction/IntInstruction.java @@ -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; diff --git a/src/main/java/net/simon987/mar/server/assembly/instruction/IntoInstruction.java b/src/main/java/net/simon987/mar/server/assembly/instruction/IntoInstruction.java new file mode 100644 index 0000000..b66efb7 --- /dev/null +++ b/src/main/java/net/simon987/mar/server/assembly/instruction/IntoInstruction.java @@ -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; + } +} diff --git a/src/main/resources/static/js/editor.js b/src/main/resources/static/js/editor.js index 828c35a..d897207 100644 --- a/src/main/resources/static/js/editor.js +++ b/src/main/resources/static/js/editor.js @@ -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) { diff --git a/src/test/java/net/simon987/mar/server/assembly/instruction/IntoInstructionTest.java b/src/test/java/net/simon987/mar/server/assembly/instruction/IntoInstructionTest.java new file mode 100644 index 0000000..47b661d --- /dev/null +++ b/src/test/java/net/simon987/mar/server/assembly/instruction/IntoInstructionTest.java @@ -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")); + } +}