Implemented updated spec.
Added new logic instructions and test program. ASM markers may now start a line with an instruction. Improved logic in location class.
This commit is contained in:
16
SPEC.txt
16
SPEC.txt
@@ -16,11 +16,11 @@ Marker (:) :XYZ
|
|||||||
|
|
||||||
Locations (@)
|
Locations (@)
|
||||||
Code ASM Type Values
|
Code ASM Type Values
|
||||||
0x0 P Port 0-255
|
0x0 P Port 0-255 | 0xFF
|
||||||
0x1 R Register A-D
|
0x1 R Register A-D
|
||||||
0x2 M Memory 0-65535
|
0x2 M Memory 0-65535 | 0xFFFF
|
||||||
0x3 I Immediate 0-65535 | 'a' | "a" | 0xFFFF
|
0x3 # Immediate 0-65535 | 0xFFFF | 'a' | "a"
|
||||||
0x4 F Flag 0-255
|
0x4 F Flag 0-255 | 0xFF
|
||||||
0x5 A Address In Register A-D
|
0x5 A Address In Register A-D
|
||||||
|
|
||||||
Instructions
|
Instructions
|
||||||
@@ -48,10 +48,10 @@ Code ASM
|
|||||||
0x31 AND R @
|
0x31 AND R @
|
||||||
0x32 OR R @
|
0x32 OR R @
|
||||||
0x33 XOR R @
|
0x33 XOR R @
|
||||||
0x33 SHL R 0-8 Shift Left
|
0x34 SHL R 0-7 Shift Left
|
||||||
0x34 SHR R 0-8 Shift Right
|
0x35 SHR R 0-7 Shift Right
|
||||||
0x35 BTS R 0-8 Bit Set
|
0x36 BTS R 0-7 Bit Set
|
||||||
0x36 BTC R 0-8 Bit Clear
|
0x37 BTC R 0-7 Bit Clear
|
||||||
Stack
|
Stack
|
||||||
0x40 CALL #|:
|
0x40 CALL #|:
|
||||||
0x41 RET
|
0x41 RET
|
||||||
|
|||||||
@@ -49,9 +49,17 @@ namespace SVM
|
|||||||
//Records marker locations
|
//Records marker locations
|
||||||
if (line.StartsWith(':'))
|
if (line.StartsWith(':'))
|
||||||
{
|
{
|
||||||
markers.Add(line.Substring(1), mempos);
|
var markerParts = line.Split(" ", 2);
|
||||||
|
markers.Add(markerParts[0].Substring(1), mempos);
|
||||||
|
if (markerParts.Length > 1 && !string.IsNullOrWhiteSpace(markerParts[1]))
|
||||||
|
{
|
||||||
|
line = markerParts[1].Trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
parts = line.Split(" ", 2, StringSplitOptions.RemoveEmptyEntries);
|
parts = line.Split(" ", 2, StringSplitOptions.RemoveEmptyEntries);
|
||||||
var op = parts[0];
|
var op = parts[0];
|
||||||
@@ -122,6 +130,7 @@ namespace SVM
|
|||||||
}
|
}
|
||||||
|
|
||||||
byte[] lineData = new byte[0];
|
byte[] lineData = new byte[0];
|
||||||
|
parts[1] = parts[1].Trim();
|
||||||
if (parts[1].StartsWith('\'') || parts[1].StartsWith('"'))
|
if (parts[1].StartsWith('\'') || parts[1].StartsWith('"'))
|
||||||
{
|
{
|
||||||
string asciiContent = string.Empty;
|
string asciiContent = string.Empty;
|
||||||
|
|||||||
17
SVM/Instructions/AND.cs
Normal file
17
SVM/Instructions/AND.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class AND : ADD
|
||||||
|
{
|
||||||
|
public override string ASM => "AND";
|
||||||
|
public override byte OP => 0x31;
|
||||||
|
|
||||||
|
protected override void Run(VM vm, byte reg, Location loc)
|
||||||
|
{
|
||||||
|
vm.R[reg] &= loc.Read(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
SVM/Instructions/BTC.cs
Normal file
18
SVM/Instructions/BTC.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class BTC : SHL
|
||||||
|
{
|
||||||
|
public override string ASM => "BTC";
|
||||||
|
|
||||||
|
public override byte OP => 0x37;
|
||||||
|
|
||||||
|
protected override void Run(VM vm, byte reg, byte bit)
|
||||||
|
{
|
||||||
|
vm.R[reg] = (ushort)(vm.R[reg] & ~(1 << bit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
SVM/Instructions/BTS.cs
Normal file
18
SVM/Instructions/BTS.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class BTS : SHL
|
||||||
|
{
|
||||||
|
public override string ASM => "BTS";
|
||||||
|
|
||||||
|
public override byte OP => 0x36;
|
||||||
|
|
||||||
|
protected override void Run(VM vm, byte reg, byte bit)
|
||||||
|
{
|
||||||
|
vm.R[reg] = (ushort)(vm.R[reg] | 1 << bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ namespace SVM.Instructions
|
|||||||
|
|
||||||
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(asm.Length == 1);
|
||||||
byte reg = Register.FromASM(asm);
|
byte reg = Register.FromASM(asm);
|
||||||
return new byte[] { OP, reg };
|
return new byte[] { OP, reg };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace SVM.Instructions
|
|
||||||
{
|
|
||||||
class CLRI : Instruction
|
|
||||||
{
|
|
||||||
public override string ASM => "CLRI";
|
|
||||||
|
|
||||||
public override byte OP => 0x62;
|
|
||||||
|
|
||||||
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
|
||||||
{
|
|
||||||
return new byte[] { OP };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Exec(VM vm, byte[] vars)
|
|
||||||
{
|
|
||||||
Debug.Assert(vars.Length == 0);
|
|
||||||
vm.RI = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToASM(byte[] vars)
|
|
||||||
{
|
|
||||||
Debug.Assert(vars.Length == 0);
|
|
||||||
return ASM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace SVM.Instructions
|
|
||||||
{
|
|
||||||
class DECI : Instruction
|
|
||||||
{
|
|
||||||
public override string ASM => "DECI";
|
|
||||||
|
|
||||||
public override byte OP => 0x64;
|
|
||||||
|
|
||||||
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
|
||||||
{
|
|
||||||
return new byte[] { OP };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Exec(VM vm, byte[] vars)
|
|
||||||
{
|
|
||||||
Debug.Assert(vars.Length == 0);
|
|
||||||
vm.RI--;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToASM(byte[] vars)
|
|
||||||
{
|
|
||||||
Debug.Assert(vars.Length == 0);
|
|
||||||
return ASM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using System.Diagnostics;
|
|
||||||
|
|
||||||
namespace SVM.Instructions
|
|
||||||
{
|
|
||||||
class INCI : Instruction
|
|
||||||
{
|
|
||||||
public override string ASM => "INCI";
|
|
||||||
|
|
||||||
public override byte OP => 0x63;
|
|
||||||
|
|
||||||
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
|
||||||
{
|
|
||||||
return new byte[] { OP };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Exec(VM vm, byte[] vars)
|
|
||||||
{
|
|
||||||
Debug.Assert(vars.Length == 0);
|
|
||||||
vm.RI++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToASM(byte[] vars)
|
|
||||||
{
|
|
||||||
Debug.Assert(vars.Length == 0);
|
|
||||||
return ASM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SVM.Instructions
|
|
||||||
{
|
|
||||||
class LOADI : Instruction
|
|
||||||
{
|
|
||||||
public override string ASM => "LOADI";
|
|
||||||
|
|
||||||
public override byte OP => 0x60;
|
|
||||||
|
|
||||||
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
|
||||||
{
|
|
||||||
var reg = Register.FromASM(asm);
|
|
||||||
return new byte[] { OP, reg };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override byte[] Decode(VM vm)
|
|
||||||
{
|
|
||||||
var reg = vm.MEM[vm.PC];
|
|
||||||
vm.PC++;
|
|
||||||
return new byte[] { reg };
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Exec(VM vm, byte[] vars)
|
|
||||||
{
|
|
||||||
Debug.Assert(vars.Length == 1);
|
|
||||||
var reg = vars[0];
|
|
||||||
Debug.Assert(reg <= VM.REGISTERS);
|
|
||||||
Run(vm, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void Run(VM vm, byte reg)
|
|
||||||
{
|
|
||||||
vm.R[reg] = vm.MEM[vm.RI];
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToASM(byte[] vars)
|
|
||||||
{
|
|
||||||
return string.Format("{0} {1}", ASM, Register.ToASM(vars[0]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace SVM.Instructions
|
namespace SVM.Instructions
|
||||||
{
|
{
|
||||||
class SETI : LOADI
|
class NOT : CLR
|
||||||
{
|
{
|
||||||
public override string ASM => "SETI";
|
public override string ASM => "NOT";
|
||||||
|
|
||||||
public override byte OP => 0x65;
|
public override byte OP => 0x30;
|
||||||
|
|
||||||
protected override void Run(VM vm, byte reg)
|
protected override void Run(VM vm, byte reg)
|
||||||
{
|
{
|
||||||
vm.RI = vm.R[reg];
|
vm.R[reg] = (ushort)~vm.R[reg];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
17
SVM/Instructions/OR.cs
Normal file
17
SVM/Instructions/OR.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class OR : ADD
|
||||||
|
{
|
||||||
|
public override string ASM => "OR";
|
||||||
|
public override byte OP => 0x32;
|
||||||
|
|
||||||
|
protected override void Run(VM vm, byte reg, Location loc)
|
||||||
|
{
|
||||||
|
vm.R[reg] |= loc.Read(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ namespace SVM.Instructions
|
|||||||
|
|
||||||
public override string ToASM(byte[] vars)
|
public override string ToASM(byte[] vars)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return ASM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SVM.Instructions
|
|
||||||
{
|
|
||||||
class SAVEI : LOADI
|
|
||||||
{
|
|
||||||
public override string ASM => "SAVEI";
|
|
||||||
|
|
||||||
public override byte OP => 0x61;
|
|
||||||
|
|
||||||
protected override void Run(VM vm, byte reg)
|
|
||||||
{
|
|
||||||
vm.MEM[vm.RI] = (byte)vm.R[reg];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
60
SVM/Instructions/SHL.cs
Normal file
60
SVM/Instructions/SHL.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class SHL : Instruction
|
||||||
|
{
|
||||||
|
public override string ASM => "SHL";
|
||||||
|
|
||||||
|
public override byte OP => 0x34;
|
||||||
|
|
||||||
|
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
||||||
|
{
|
||||||
|
var parts = asm.Split(" ");
|
||||||
|
Debug.Assert(parts.Length == 2);
|
||||||
|
byte reg = Register.FromASM(parts[0]);
|
||||||
|
byte bit = byte.Parse(parts[1]);
|
||||||
|
Debug.Assert(bit < 8);
|
||||||
|
|
||||||
|
return new byte[] { OP, reg, bit };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] Decode(VM vm)
|
||||||
|
{
|
||||||
|
var bc = vm.MEM.Subset(vm.PC, 2);
|
||||||
|
vm.PC += 2;
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Exec(VM vm, byte[] vars)
|
||||||
|
{
|
||||||
|
Debug.Assert(vars.Length == 2);
|
||||||
|
|
||||||
|
byte reg = vars[0];
|
||||||
|
byte bit = vars[1];
|
||||||
|
|
||||||
|
Debug.Assert(reg <= VM.REGISTERS);
|
||||||
|
Debug.Assert(bit < 8);
|
||||||
|
|
||||||
|
Run(vm, reg, bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Run(VM vm, byte reg, byte bit)
|
||||||
|
{
|
||||||
|
vm.R[reg] = (ushort)(vm.R[reg] << bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToASM(byte[] vars)
|
||||||
|
{
|
||||||
|
Debug.Assert(vars.Length == 2);
|
||||||
|
|
||||||
|
byte reg = vars[0];
|
||||||
|
byte bit = vars[1];
|
||||||
|
|
||||||
|
return string.Format("{0} {1} {2}", ASM, Register.ToASM(reg), bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
SVM/Instructions/SHR.cs
Normal file
18
SVM/Instructions/SHR.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class SHR : SHL
|
||||||
|
{
|
||||||
|
public override string ASM => "SHR";
|
||||||
|
|
||||||
|
public override byte OP => 0x35;
|
||||||
|
|
||||||
|
protected override void Run(VM vm, byte reg, byte bit)
|
||||||
|
{
|
||||||
|
vm.R[reg] = (ushort)(vm.R[reg] >> bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
SVM/Instructions/XOR.cs
Normal file
18
SVM/Instructions/XOR.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class XOR : ADD
|
||||||
|
{
|
||||||
|
public override string ASM => "XOR";
|
||||||
|
|
||||||
|
public override byte OP => 0x33;
|
||||||
|
|
||||||
|
protected override void Run(VM vm, byte reg, Location loc)
|
||||||
|
{
|
||||||
|
vm.R[reg] ^= loc.Read(vm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
137
SVM/Location.cs
137
SVM/Location.cs
@@ -9,12 +9,16 @@ namespace SVM
|
|||||||
{
|
{
|
||||||
public const byte PORT_CODE = 0x0;
|
public const byte PORT_CODE = 0x0;
|
||||||
public const string PORT_ASM = "P";
|
public const string PORT_ASM = "P";
|
||||||
public const byte REG_CODE = 0x1;
|
public const byte REGISTER_CODE = 0x1;
|
||||||
public const string REG_ASM = "R";
|
public const string REGISTER_ASM = "R";
|
||||||
public const byte MEM_CODE = 0x2;
|
public const byte MEMORY_CODE = 0x2;
|
||||||
public const string MEM_ASM = "M";
|
public const string MEMORY_ASM = "M";
|
||||||
public const byte LITERAL_CODE = 0x3;
|
public const byte IMMEDIATE_CODE = 0x3;
|
||||||
public const string LITERAL_ASM = "L";
|
public const string IMMEDIATE_ASM = "I";
|
||||||
|
public const byte FLAG_CODE = 0x4;
|
||||||
|
public const string FLAG_ASM = "F";
|
||||||
|
public const byte ADDRESS_CODE = 0x5;
|
||||||
|
public const string ADDRESS_ASM = "A";
|
||||||
|
|
||||||
public const int SIZE = 3;
|
public const int SIZE = 3;
|
||||||
|
|
||||||
@@ -23,9 +27,11 @@ namespace SVM
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PORT_ASM: return PORT_CODE;
|
case PORT_ASM: return PORT_CODE;
|
||||||
case REG_ASM: return REG_CODE;
|
case REGISTER_ASM: return REGISTER_CODE;
|
||||||
case MEM_ASM: return MEM_CODE;
|
case MEMORY_ASM: return MEMORY_CODE;
|
||||||
case LITERAL_ASM: return LITERAL_CODE;
|
case IMMEDIATE_ASM: return IMMEDIATE_CODE;
|
||||||
|
case FLAG_ASM: return FLAG_CODE;
|
||||||
|
case ADDRESS_ASM:return ADDRESS_CODE;
|
||||||
default: throw new Exception("Invalid location type");
|
default: throw new Exception("Invalid location type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,38 +40,63 @@ namespace SVM
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PORT_CODE: return PORT_ASM;
|
case PORT_CODE: return PORT_ASM;
|
||||||
case REG_CODE: return REG_ASM;
|
case REGISTER_CODE: return REGISTER_ASM;
|
||||||
case MEM_CODE: return MEM_ASM;
|
case MEMORY_CODE: return MEMORY_ASM;
|
||||||
case LITERAL_CODE: return LITERAL_ASM;
|
case IMMEDIATE_CODE: return IMMEDIATE_ASM;
|
||||||
|
case FLAG_CODE: return FLAG_ASM;
|
||||||
|
case ADDRESS_CODE: return ADDRESS_ASM;
|
||||||
default: throw new Exception("Invalid location type");
|
default: throw new Exception("Invalid location type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Location FromASM(string asm)
|
public static Location FromASM(string asm)
|
||||||
{
|
{
|
||||||
var parts = asm.Split(" ", 2);
|
Debug.Assert(asm.Length > 1);
|
||||||
Debug.Assert(parts.Length > 0);
|
asm = asm.Replace(" ", "");
|
||||||
byte type = EncodeType(parts[0]);
|
byte type = EncodeType(asm[0].ToString());
|
||||||
ushort loc = 0;
|
ushort loc = 0;
|
||||||
Debug.Assert(parts.Length == 2);
|
string locVal = asm.Substring(1);
|
||||||
string locVal = parts[1];
|
switch(type)
|
||||||
if (locVal.StartsWith('\'') || locVal.StartsWith('"'))
|
|
||||||
{
|
{
|
||||||
Debug.Assert(locVal.Length > 1);
|
case PORT_CODE:
|
||||||
loc = (byte)locVal[1];
|
case FLAG_CODE:
|
||||||
}
|
loc = byte.Parse(locVal);
|
||||||
else if (locVal.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
|
break;
|
||||||
{
|
case ADDRESS_CODE:
|
||||||
Debug.Assert(locVal.Length > 2);
|
case REGISTER_CODE:
|
||||||
loc = ushort.Parse(locVal.Substring(2), System.Globalization.NumberStyles.HexNumber);
|
loc = Register.FromASM(locVal);
|
||||||
}
|
break;
|
||||||
else
|
case MEMORY_CODE:
|
||||||
{
|
loc = ReadNumber(locVal, true);
|
||||||
loc = ushort.Parse(locVal);
|
break;
|
||||||
|
case IMMEDIATE_CODE:
|
||||||
|
loc = ReadNumber(locVal, false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Location(type, loc);
|
return new Location(type, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ushort ReadNumber(string val, bool allowChar)
|
||||||
|
{
|
||||||
|
ushort converted;
|
||||||
|
if (allowChar && (val.StartsWith('\'') || val.StartsWith('"')))
|
||||||
|
{
|
||||||
|
Debug.Assert(val.Length > 1);
|
||||||
|
converted = (byte)val[1];
|
||||||
|
}
|
||||||
|
else if (val.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
Debug.Assert(val.Length > 2);
|
||||||
|
converted = ushort.Parse(val.Substring(2), System.Globalization.NumberStyles.HexNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
converted = ushort.Parse(val);
|
||||||
|
}
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
public static Location FromByteCode(byte[] data, int start)
|
public static Location FromByteCode(byte[] data, int start)
|
||||||
{
|
{
|
||||||
Debug.Assert(data.Length > start);
|
Debug.Assert(data.Length > start);
|
||||||
@@ -90,13 +121,20 @@ namespace SVM
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PORT_CODE:
|
case PORT_CODE:
|
||||||
|
Debug.Assert(loc <= VM.PORTS);
|
||||||
return vm.Ports[loc].Read();
|
return vm.Ports[loc].Read();
|
||||||
case REG_CODE:
|
case REGISTER_CODE:
|
||||||
|
Debug.Assert(loc <= VM.REGISTERS);
|
||||||
return vm.R[loc];
|
return vm.R[loc];
|
||||||
case MEM_CODE:
|
case MEMORY_CODE:
|
||||||
return vm.MEM[loc];
|
return vm.MEM[loc];
|
||||||
case LITERAL_CODE:
|
case IMMEDIATE_CODE:
|
||||||
return loc;
|
return loc;
|
||||||
|
case FLAG_CODE:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
case ADDRESS_CODE:
|
||||||
|
Debug.Assert(loc <= VM.REGISTERS);
|
||||||
|
return vm.MEM[vm.R[loc]];
|
||||||
default: throw new Exception("Invalid location type");
|
default: throw new Exception("Invalid location type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,16 +143,24 @@ namespace SVM
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case PORT_CODE:
|
case PORT_CODE:
|
||||||
vm.Ports[loc].Write((byte)val);
|
Debug.Assert(loc <= VM.PORTS);
|
||||||
|
vm.Ports[loc].Write((byte)(val & 0xFF));
|
||||||
break;
|
break;
|
||||||
case REG_CODE:
|
case REGISTER_CODE:
|
||||||
|
Debug.Assert(loc <= VM.REGISTERS);
|
||||||
vm.R[loc] = val;
|
vm.R[loc] = val;
|
||||||
break;
|
break;
|
||||||
case MEM_CODE:
|
case MEMORY_CODE:
|
||||||
vm.MEM[loc] = (byte)val;
|
vm.MEM[loc] = (byte)(val & 0xFF);
|
||||||
break;
|
break;
|
||||||
case LITERAL_CODE:
|
case IMMEDIATE_CODE:
|
||||||
throw new Exception("Invalid operation");
|
throw new Exception("Invalid operation");
|
||||||
|
case FLAG_CODE:
|
||||||
|
throw new NotImplementedException();
|
||||||
|
case ADDRESS_CODE:
|
||||||
|
Debug.Assert(loc <= VM.REGISTERS);
|
||||||
|
vm.MEM[vm.R[loc]] = (byte)(val & 0xFF);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid location type");
|
throw new Exception("Invalid location type");
|
||||||
}
|
}
|
||||||
@@ -122,14 +168,25 @@ namespace SVM
|
|||||||
|
|
||||||
public byte[] Encode()
|
public byte[] Encode()
|
||||||
{
|
{
|
||||||
byte ub = (byte)((loc & 0xFF00) >> 8);
|
return new byte[] { type, loc.HiByte(), loc.LoByte() };
|
||||||
byte lb = (byte)(loc & 0xFF);
|
|
||||||
return new byte[] { type, ub, lb };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToASM()
|
public string ToASM()
|
||||||
{
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case PORT_CODE:
|
||||||
|
case FLAG_CODE:
|
||||||
|
return string.Format("{0}{1}", DecodeType(type), loc);
|
||||||
|
case REGISTER_CODE:
|
||||||
|
return string.Format("R{0}", Register.ToASM((byte)loc));
|
||||||
|
case ADDRESS_CODE:
|
||||||
|
return string.Format("A{0}", Register.ToASM((byte)loc));
|
||||||
|
case IMMEDIATE_CODE:
|
||||||
|
case MEMORY_CODE:
|
||||||
|
default:
|
||||||
return string.Format("{0}0x{1:X}", DecodeType(type), loc);
|
return string.Format("{0}0x{1:X}", DecodeType(type), loc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,26 +1,22 @@
|
|||||||
ORIGIN 0
|
ORIGIN 0
|
||||||
JMP :PGM
|
JMP :PGM
|
||||||
|
|
||||||
:WRITESTR
|
:WRITESTR LOAD C RA
|
||||||
SETI A
|
:WRITESTR_L LOAD A AC
|
||||||
:WRITESTR_LOOP
|
JZ A :WRITESTR_R
|
||||||
LOADI A
|
|
||||||
JZ A :WRITESTR_RET
|
|
||||||
SAVE A P0
|
SAVE A P0
|
||||||
INCI
|
INC C
|
||||||
JMP :WRITESTR_LOOP
|
JMP :WRITESTR_L
|
||||||
:WRITESTR_RET
|
:WRITESTR_R CLR C
|
||||||
RET
|
RET
|
||||||
|
|
||||||
:WRITENL
|
:WRITENL LOAD A I13
|
||||||
LOAD A L 13
|
|
||||||
SAVE A P0
|
SAVE A P0
|
||||||
LOAD A L 10
|
LOAD A I10
|
||||||
SAVE A P0
|
SAVE A P0
|
||||||
RET
|
RET
|
||||||
|
|
||||||
:PGM
|
:PGM LOAD A I0x100
|
||||||
LOAD A L 0x100
|
|
||||||
CALL :WRITESTR
|
CALL :WRITESTR
|
||||||
CALL :WRITENL
|
CALL :WRITENL
|
||||||
HALT
|
HALT
|
||||||
|
|||||||
@@ -2,36 +2,33 @@
|
|||||||
#Print string 5 times
|
#Print string 5 times
|
||||||
|
|
||||||
CLR B
|
CLR B
|
||||||
ADD B L 5
|
ADD B I5
|
||||||
ADD B L 48
|
ADD B I48
|
||||||
SAVE B P0
|
SAVE B P0
|
||||||
SUB B L 48
|
SUB B I48
|
||||||
|
|
||||||
LOAD A L 0x300 #Set string start
|
LOAD C I0x300 #Set string start
|
||||||
SETI A
|
|
||||||
JMP :PRINTA
|
|
||||||
|
|
||||||
:PRINTA #Print until zero
|
:PRINTA #Print until zero
|
||||||
LOADI A
|
LOAD A AC
|
||||||
JZ A :NEWLINE
|
JZ A :NEWLINE
|
||||||
SAVE A P0
|
SAVE A P0
|
||||||
INCI
|
INC C
|
||||||
JMP :PRINTA
|
JMP :PRINTA
|
||||||
|
|
||||||
:NEWLINE #New Line
|
:NEWLINE #New Line
|
||||||
LOAD A L 13
|
LOAD A I13
|
||||||
SAVE A P0
|
SAVE A P0
|
||||||
LOAD A L 10
|
LOAD A I10
|
||||||
SAVE A P0
|
SAVE A P0
|
||||||
|
|
||||||
LOAD A L 0x300 #Set string start
|
LOAD C I0x300 #Set string start
|
||||||
SETI A
|
|
||||||
|
|
||||||
DEC B #Check Counter and stop if 5 printed
|
DEC B #Check Counter and stop if 5 printed
|
||||||
JZ B :STOP
|
JZ B :STOP
|
||||||
ADD B L 48
|
ADD B I48
|
||||||
SAVE B P0
|
SAVE B P0
|
||||||
SUB B L 48
|
SUB B I48
|
||||||
JMP :PRINTA
|
JMP :PRINTA
|
||||||
|
|
||||||
:STOP
|
:STOP
|
||||||
|
|||||||
11
SVM/PGM/LOGIC.txt
Normal file
11
SVM/PGM/LOGIC.txt
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
ORIGIN 0
|
||||||
|
LOAD A I1
|
||||||
|
JMP :PGM
|
||||||
|
|
||||||
|
:PGM SHL A 1
|
||||||
|
NOT A
|
||||||
|
NOT A
|
||||||
|
JZ A :EXIT
|
||||||
|
JMP :PGM
|
||||||
|
|
||||||
|
:EXIT HALT
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="PGM\CALL.txt" />
|
<None Remove="PGM\CALL.txt" />
|
||||||
<None Remove="PGM\HELLO.txt" />
|
<None Remove="PGM\HELLO.txt" />
|
||||||
|
<None Remove="PGM\LOGIC.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -19,6 +20,9 @@
|
|||||||
<Content Include="PGM\HELLO.txt">
|
<Content Include="PGM\HELLO.txt">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="PGM\LOGIC.txt">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ namespace SVM
|
|||||||
var pc = PC;
|
var pc = PC;
|
||||||
var instr = instructions[MEM[PC++]];
|
var instr = instructions[MEM[PC++]];
|
||||||
byte[] decoded = instr.Decode(this);
|
byte[] decoded = instr.Decode(this);
|
||||||
//Console.WriteLine("A{0} B{1} C{2} D{3}", R[0], R[1], R[2], R[3]);
|
Console.Write("{4:X4} | A{0:X3} B{1:X3} C{2:X3} D{3:X3} | ", R[0], R[1], R[2], R[3], pc);
|
||||||
//Console.WriteLine("0x{0:X4} {1}", pc, instr.ToASM(decoded));
|
Console.WriteLine("0x{0:X4} {1}", pc, instr.ToASM(decoded));
|
||||||
instr.Exec(this, decoded);
|
instr.Exec(this, decoded);
|
||||||
//Console.ReadKey(true);
|
//Console.ReadKey(true);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user