Implemeted Flag support and flag CONSTS.
Implmeneted ALIAS assembler instruction, JBC & JBS instructions.
This commit is contained in:
12
FLAGS.md
12
FLAGS.md
@@ -8,11 +8,11 @@ Bits marked N/A read as zero and writing values will not have an effect.
|
|||||||
|
|
||||||
### Status | CONSTS | 0x00
|
### Status | CONSTS | 0x00
|
||||||
|
|
||||||
| | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
| | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
|
||||||
| --------------- | --- | --- | --- | --- | --- | --- | --- | --- |
|
| --------------- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
| **Read/Write** | | | | | | | R/W | R |
|
| **Read/Write** | | | | | R | R/W | R/W | R |
|
||||||
| **Defaults** | | | | | | | 1 | X |
|
| **Default ** | | | | | X | 1 | 1 | X |
|
||||||
| **Name** | N/A | N/A | N/A | N/A | N/A | N/A | Enabled | Available |
|
| **Name** | N/A | N/A | N/A | N/A | ReadAvailable | ReadBlock | Enabled | Available |
|
||||||
|
|
||||||
### Cursor X | CONPOSX | 0x01
|
### Cursor X | CONPOSX | 0x01
|
||||||
|
|
||||||
@@ -50,9 +50,9 @@ Trap status and settings
|
|||||||
<!--
|
<!--
|
||||||
### Name | ALIAS | 0x00
|
### Name | ALIAS | 0x00
|
||||||
|
|
||||||
| | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
| | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
|
||||||
| --------------- | --- | --- | --- | --- | --- | --- | --- | --- |
|
| --------------- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||||
| **Read/Write** | | | | | | | | |
|
| **Read/Write** | | | | | | | | |
|
||||||
| **Defaults** | | | | | | | | |
|
| **Default ** | | | | | | | | |
|
||||||
| **Name** | | | | | | | | |
|
| **Name** | | | | | | | | |
|
||||||
-->
|
-->
|
||||||
7
SPEC.md
7
SPEC.md
@@ -71,8 +71,8 @@
|
|||||||
| 0x51 | JMP | [#\|:] |
|
| 0x51 | JMP | [#\|:] |
|
||||||
| 0x52 | JZ | [R] [#\|:] |
|
| 0x52 | JZ | [R] [#\|:] |
|
||||||
| 0x53 | JNZ | [R] [#\|:] |
|
| 0x53 | JNZ | [R] [#\|:] |
|
||||||
| 0x54 | JBS | [R] [0-7] [#\|:] |
|
| 0x54 | JBS | [R] [1-8] [#\|:] |
|
||||||
| 0x55 | JBC | [R] [0-7] [#\|:] |
|
| 0x55 | JBC | [R] [1-8] [#\|:] |
|
||||||
| **System**
|
| **System**
|
||||||
| 0x60 | SYS | [0-255] | Syscall, parameters depend on call
|
| 0x60 | SYS | [0-255] | Syscall, parameters depend on call
|
||||||
|
|
||||||
@@ -80,7 +80,8 @@
|
|||||||
|
|
||||||
| ASM | Parameters | Notes |
|
| ASM | Parameters | Notes |
|
||||||
| ------ | ---------- | ------------ |
|
| ------ | ---------- | ------------ |
|
||||||
| ORIGIN | [#] | Sets the Memory Address for the next instruction |
|
| ORIGIN | [#] | Sets the Memory Address for the next instruction
|
||||||
|
| ALIAS | X Y | Replaces word X with word Y where X and Y are alpha numberic, only applies after the instruction
|
||||||
|
|
||||||
## Program Format
|
## Program Format
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
namespace SVM
|
namespace SVM
|
||||||
{
|
{
|
||||||
@@ -28,8 +29,11 @@ namespace SVM
|
|||||||
ushort lastpos = 0;
|
ushort lastpos = 0;
|
||||||
string line;
|
string line;
|
||||||
string[] parts;
|
string[] parts;
|
||||||
|
|
||||||
Dictionary<string, ushort> markers = new Dictionary<string, ushort>();
|
Dictionary<string, ushort> markers = new Dictionary<string, ushort>();
|
||||||
Dictionary<string, List<ushort>> markerUses = new Dictionary<string, List<ushort>>();
|
Dictionary<string, List<ushort>> markerUses = new Dictionary<string, List<ushort>>();
|
||||||
|
Dictionary<string, string> aliases = new Dictionary<string, string>();
|
||||||
|
|
||||||
//Encode ops until memory section
|
//Encode ops until memory section
|
||||||
for (; i < lines.Length; i++)
|
for (; i < lines.Length; i++)
|
||||||
{
|
{
|
||||||
@@ -46,6 +50,12 @@ namespace SVM
|
|||||||
line = line.Replace(" ", " ");
|
line = line.Replace(" ", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Replace aliases
|
||||||
|
foreach(var alias in aliases)
|
||||||
|
{
|
||||||
|
line = Regex.Replace(line, string.Format(@"(^|\b){0}($|\b)", alias.Key), alias.Value);
|
||||||
|
}
|
||||||
|
|
||||||
//Records marker locations
|
//Records marker locations
|
||||||
if (line.StartsWith(':'))
|
if (line.StartsWith(':'))
|
||||||
{
|
{
|
||||||
@@ -77,6 +87,18 @@ namespace SVM
|
|||||||
if (mempos > lastpos) lastpos = mempos;
|
if (mempos > lastpos) lastpos = mempos;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (op == "ALIAS")
|
||||||
|
{
|
||||||
|
Debug.Assert(parts.Length == 2);
|
||||||
|
var aliasParts = parts[1].Split(' ', 2);
|
||||||
|
Debug.Assert(aliasParts.Length == 2);
|
||||||
|
if (aliases.ContainsKey(aliasParts[0]))
|
||||||
|
{
|
||||||
|
aliases.Remove(aliasParts[0]);
|
||||||
|
}
|
||||||
|
aliases.Add(aliasParts[0], aliasParts[1]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
var instr = instructions.First(x => x.ASM == op);
|
var instr = instructions.First(x => x.ASM == op);
|
||||||
|
|
||||||
|
|||||||
33
SVM/Flag.cs
Normal file
33
SVM/Flag.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM
|
||||||
|
{
|
||||||
|
abstract class Flag
|
||||||
|
{
|
||||||
|
public static Flag[] GetAllFlags()
|
||||||
|
{
|
||||||
|
var types = from t in Assembly.GetAssembly(typeof(Flag)).GetTypes()
|
||||||
|
where t.IsSubclassOf(typeof(Flag))
|
||||||
|
select t;
|
||||||
|
|
||||||
|
var flags = new List<Flag>();
|
||||||
|
|
||||||
|
foreach (var t in types)
|
||||||
|
{
|
||||||
|
flags.Add((Flag)Activator.CreateInstance(t));
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract string ASM { get; }
|
||||||
|
public abstract byte Address { get; }
|
||||||
|
|
||||||
|
public abstract byte Read(VM vm);
|
||||||
|
public abstract void Write(VM vm, byte val);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
SVM/Flags/CONSTS.cs
Normal file
51
SVM/Flags/CONSTS.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
using SVM.Ports;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Flags
|
||||||
|
{
|
||||||
|
class CONSTS : Flag
|
||||||
|
{
|
||||||
|
public const byte AVAILABLE = 1;
|
||||||
|
public const byte ENABLED = 2;
|
||||||
|
public const byte READBLOCK = 4;
|
||||||
|
public const byte READAVAILABLE = 8;
|
||||||
|
|
||||||
|
public override string ASM => "CONSTS";
|
||||||
|
|
||||||
|
public override byte Address => 0x00;
|
||||||
|
|
||||||
|
public override byte Read(VM vm)
|
||||||
|
{
|
||||||
|
var port = vm.Ports[0] as ConsolePort;
|
||||||
|
Debug.Assert(port != null);
|
||||||
|
|
||||||
|
byte result = AVAILABLE;
|
||||||
|
if (port.Enabled)
|
||||||
|
{
|
||||||
|
result |= ENABLED;
|
||||||
|
}
|
||||||
|
if (port.ReadBlock)
|
||||||
|
{
|
||||||
|
result |= READBLOCK;
|
||||||
|
}
|
||||||
|
if (Console.KeyAvailable)
|
||||||
|
{
|
||||||
|
result |= READAVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(VM vm, byte val)
|
||||||
|
{
|
||||||
|
var port = vm.Ports[0] as ConsolePort;
|
||||||
|
Debug.Assert(port != null);
|
||||||
|
|
||||||
|
port.Enabled = (val & ENABLED) == ENABLED;
|
||||||
|
port.ReadBlock = (val & READBLOCK) == READBLOCK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
83
SVM/Instructions/JBC.cs
Normal file
83
SVM/Instructions/JBC.cs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class JBC : Instruction
|
||||||
|
{
|
||||||
|
public override string ASM => "JBC";
|
||||||
|
|
||||||
|
public override byte OP => 0x55;
|
||||||
|
|
||||||
|
public override byte[] Encode(string asm, Dictionary<string, ushort> markerRefs)
|
||||||
|
{
|
||||||
|
var parts = asm.Split(' ');
|
||||||
|
Debug.Assert(parts.Length == 3);
|
||||||
|
|
||||||
|
byte reg = Register.FromASM(parts[0]);
|
||||||
|
|
||||||
|
byte bit = byte.Parse(parts[1]);
|
||||||
|
Debug.Assert(bit >= 1 && bit <= 8);
|
||||||
|
|
||||||
|
ushort loc = 0;
|
||||||
|
if (parts[2].StartsWith(':') && markerRefs != null)
|
||||||
|
{
|
||||||
|
markerRefs.Add(parts[2].Substring(1), 3);
|
||||||
|
}
|
||||||
|
else if (parts[2].StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
loc = ushort.Parse(parts[2].Substring(2), System.Globalization.NumberStyles.HexNumber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loc = ushort.Parse(parts[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new byte[] { OP, reg, bit, loc.HiByte(), loc.LoByte() };
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte[] Decode(VM vm)
|
||||||
|
{
|
||||||
|
var bc = vm.MEM.Subset(vm.PC, 4);
|
||||||
|
vm.PC += 4;
|
||||||
|
return bc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Exec(VM vm, byte[] vars)
|
||||||
|
{
|
||||||
|
Debug.Assert(vars.Length == 4);
|
||||||
|
|
||||||
|
byte reg = vars[0];
|
||||||
|
Debug.Assert(reg <= VM.REGISTERS);
|
||||||
|
|
||||||
|
byte bit = vars[1];
|
||||||
|
Debug.Assert(bit >= 1 && bit <= 8);
|
||||||
|
|
||||||
|
ushort loc = (ushort)((vars[2] << 8) + vars[3]);
|
||||||
|
|
||||||
|
if (CheckJump(vm, reg, bit))
|
||||||
|
{
|
||||||
|
vm.PC = loc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual bool CheckJump(VM vm, byte reg, byte bit)
|
||||||
|
{
|
||||||
|
byte compare = (byte)(1 << bit - 1);
|
||||||
|
return (vm.R[reg] & compare) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToASM(byte[] vars)
|
||||||
|
{
|
||||||
|
Debug.Assert(vars.Length == 4);
|
||||||
|
byte reg = vars[0];
|
||||||
|
Debug.Assert(reg <= VM.REGISTERS);
|
||||||
|
byte bit = vars[1];
|
||||||
|
ushort loc = (ushort)((vars[2] << 8) + vars[3]);
|
||||||
|
|
||||||
|
return string.Format("{0} {1} {2} {3}", ASM, Register.ToASM(reg), bit, string.Format("0x{0:X}", loc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
SVM/Instructions/JBS.cs
Normal file
19
SVM/Instructions/JBS.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace SVM.Instructions
|
||||||
|
{
|
||||||
|
class JBS : JBC
|
||||||
|
{
|
||||||
|
public override string ASM => "JBS";
|
||||||
|
|
||||||
|
public override byte OP => 0x54;
|
||||||
|
|
||||||
|
protected override bool CheckJump(VM vm, byte reg, byte bit)
|
||||||
|
{
|
||||||
|
byte compare = (byte)(1 << bit - 1);
|
||||||
|
return (vm.R[reg] & compare) == compare;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,7 +44,7 @@ namespace SVM.Instructions
|
|||||||
|
|
||||||
protected virtual void Run(VM vm, byte reg, byte bit)
|
protected virtual void Run(VM vm, byte reg, byte bit)
|
||||||
{
|
{
|
||||||
vm.R[reg] = (ushort)(vm.R[reg] << bit);
|
vm.R[reg] = (ushort)(vm.R[reg] << bit-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToASM(byte[] vars)
|
public override string ToASM(byte[] vars)
|
||||||
|
|||||||
@@ -15,9 +15,7 @@ namespace SVM
|
|||||||
public const string MEMORY_ASM = "M";
|
public const string MEMORY_ASM = "M";
|
||||||
public const byte IMMEDIATE_CODE = 0x3;
|
public const byte IMMEDIATE_CODE = 0x3;
|
||||||
public const string IMMEDIATE_ASM = "I";
|
public const string IMMEDIATE_ASM = "I";
|
||||||
public const byte FLAG_CODE = 0x4;
|
public const byte ADDRESS_CODE = 0x4;
|
||||||
public const string FLAG_ASM = "F";
|
|
||||||
public const byte ADDRESS_CODE = 0x5;
|
|
||||||
public const string ADDRESS_ASM = "A";
|
public const string ADDRESS_ASM = "A";
|
||||||
|
|
||||||
public const int SIZE = 3;
|
public const int SIZE = 3;
|
||||||
@@ -30,7 +28,6 @@ namespace SVM
|
|||||||
case REGISTER_ASM: return REGISTER_CODE;
|
case REGISTER_ASM: return REGISTER_CODE;
|
||||||
case MEMORY_ASM: return MEMORY_CODE;
|
case MEMORY_ASM: return MEMORY_CODE;
|
||||||
case IMMEDIATE_ASM: return IMMEDIATE_CODE;
|
case IMMEDIATE_ASM: return IMMEDIATE_CODE;
|
||||||
case FLAG_ASM: return FLAG_CODE;
|
|
||||||
case ADDRESS_ASM:return ADDRESS_CODE;
|
case ADDRESS_ASM:return ADDRESS_CODE;
|
||||||
default: throw new Exception("Invalid location type");
|
default: throw new Exception("Invalid location type");
|
||||||
}
|
}
|
||||||
@@ -43,7 +40,6 @@ namespace SVM
|
|||||||
case REGISTER_CODE: return REGISTER_ASM;
|
case REGISTER_CODE: return REGISTER_ASM;
|
||||||
case MEMORY_CODE: return MEMORY_ASM;
|
case MEMORY_CODE: return MEMORY_ASM;
|
||||||
case IMMEDIATE_CODE: return IMMEDIATE_ASM;
|
case IMMEDIATE_CODE: return IMMEDIATE_ASM;
|
||||||
case FLAG_CODE: return FLAG_ASM;
|
|
||||||
case ADDRESS_CODE: return ADDRESS_ASM;
|
case ADDRESS_CODE: return ADDRESS_ASM;
|
||||||
default: throw new Exception("Invalid location type");
|
default: throw new Exception("Invalid location type");
|
||||||
}
|
}
|
||||||
@@ -59,7 +55,6 @@ namespace SVM
|
|||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case PORT_CODE:
|
case PORT_CODE:
|
||||||
case FLAG_CODE:
|
|
||||||
loc = byte.Parse(locVal);
|
loc = byte.Parse(locVal);
|
||||||
break;
|
break;
|
||||||
case ADDRESS_CODE:
|
case ADDRESS_CODE:
|
||||||
@@ -127,14 +122,12 @@ namespace SVM
|
|||||||
Debug.Assert(loc <= VM.REGISTERS);
|
Debug.Assert(loc <= VM.REGISTERS);
|
||||||
return vm.R[loc];
|
return vm.R[loc];
|
||||||
case MEMORY_CODE:
|
case MEMORY_CODE:
|
||||||
return vm.MEM[loc];
|
return vm.Read(loc);
|
||||||
case IMMEDIATE_CODE:
|
case IMMEDIATE_CODE:
|
||||||
return loc;
|
return loc;
|
||||||
case FLAG_CODE:
|
|
||||||
throw new NotImplementedException();
|
|
||||||
case ADDRESS_CODE:
|
case ADDRESS_CODE:
|
||||||
Debug.Assert(loc <= VM.REGISTERS);
|
Debug.Assert(loc <= VM.REGISTERS);
|
||||||
return vm.MEM[vm.R[loc]];
|
return vm.Read(vm.R[loc]);
|
||||||
default: throw new Exception("Invalid location type");
|
default: throw new Exception("Invalid location type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,15 +144,13 @@ namespace SVM
|
|||||||
vm.R[loc] = val;
|
vm.R[loc] = val;
|
||||||
break;
|
break;
|
||||||
case MEMORY_CODE:
|
case MEMORY_CODE:
|
||||||
vm.MEM[loc] = (byte)(val & 0xFF);
|
vm.Write(loc, (byte)(val & 0xFF));
|
||||||
break;
|
break;
|
||||||
case IMMEDIATE_CODE:
|
case IMMEDIATE_CODE:
|
||||||
throw new Exception("Invalid operation");
|
throw new Exception("Invalid operation");
|
||||||
case FLAG_CODE:
|
|
||||||
throw new NotImplementedException();
|
|
||||||
case ADDRESS_CODE:
|
case ADDRESS_CODE:
|
||||||
Debug.Assert(loc <= VM.REGISTERS);
|
Debug.Assert(loc <= VM.REGISTERS);
|
||||||
vm.MEM[vm.R[loc]] = (byte)(val & 0xFF);
|
vm.Write(vm.R[loc], (byte)(val & 0xFF));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception("Invalid location type");
|
throw new Exception("Invalid location type");
|
||||||
@@ -176,7 +167,6 @@ namespace SVM
|
|||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case PORT_CODE:
|
case PORT_CODE:
|
||||||
case FLAG_CODE:
|
|
||||||
return string.Format("{0}{1}", DecodeType(type), loc);
|
return string.Format("{0}{1}", DecodeType(type), loc);
|
||||||
case REGISTER_CODE:
|
case REGISTER_CODE:
|
||||||
return string.Format("R{0}", Register.ToASM((byte)loc));
|
return string.Format("R{0}", Register.ToASM((byte)loc));
|
||||||
|
|||||||
52
SVM/PGM/FlagTest.txt
Normal file
52
SVM/PGM/FlagTest.txt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
ALIAS F_CONSTS 0xFF00
|
||||||
|
ALIAS STR_ENABLED 0x100
|
||||||
|
ALIAS STR_AVAILABLE 0x110
|
||||||
|
ALIAS STR_READBLOCK 0x120
|
||||||
|
ALIAS STR_READAVAILABLE 0x130
|
||||||
|
ALIAS STR_YES 0x140
|
||||||
|
ALIAS STR_NO 0x150
|
||||||
|
|
||||||
|
ORIGIN 0
|
||||||
|
LOAD D M F_CONSTS # Read the flag into reg D
|
||||||
|
|
||||||
|
LOAD A I STR_ENABLED
|
||||||
|
CALL :WSTR
|
||||||
|
JBS D 2 :ENYES # Check for enabled
|
||||||
|
LOAD A I STR_NO # Set str to NO if enabled bit not set
|
||||||
|
JMP :ENWR
|
||||||
|
:ENYES LOAD A I STR_YES
|
||||||
|
:ENWR CALL :WSTR
|
||||||
|
CALL :WNL
|
||||||
|
|
||||||
|
LOAD A I STR_READAVAILABLE
|
||||||
|
CALL :WSTR
|
||||||
|
JBS D 4 :RAYES
|
||||||
|
LOAD A I STR_NO
|
||||||
|
JMP :RAWR
|
||||||
|
:RAYES LOAD A I STR_YES
|
||||||
|
:RAWR CALL :WSTR
|
||||||
|
CALL :WNL
|
||||||
|
|
||||||
|
HALT
|
||||||
|
|
||||||
|
:WSTR LOAD C RA
|
||||||
|
:WSTR_L LOAD A AC
|
||||||
|
JZ A :WSTR_R
|
||||||
|
SAVE A P0
|
||||||
|
INC C
|
||||||
|
JMP :WSTR_L
|
||||||
|
:WSTR_R RET
|
||||||
|
|
||||||
|
:WNL LOAD A I13
|
||||||
|
SAVE A P0
|
||||||
|
LOAD A I10
|
||||||
|
SAVE A P0
|
||||||
|
RET
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
0x100 "Enabled "
|
||||||
|
0x110 "Available "
|
||||||
|
0x120 "ReadBlock "
|
||||||
|
0x130 "ReadAvailable "
|
||||||
|
0x140 "Yes"
|
||||||
|
0x150 "No"
|
||||||
@@ -6,19 +6,32 @@ namespace SVM.Ports
|
|||||||
{
|
{
|
||||||
class ConsolePort : Port
|
class ConsolePort : Port
|
||||||
{
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public bool ReadBlock { get; set; }
|
||||||
|
|
||||||
public ConsolePort(VM vm)
|
public ConsolePort(VM vm)
|
||||||
: base(vm)
|
: base(vm)
|
||||||
{ }
|
{
|
||||||
|
Enabled = true;
|
||||||
|
ReadBlock = true;
|
||||||
|
}
|
||||||
|
|
||||||
public override ushort Read()
|
public override ushort Read()
|
||||||
|
{
|
||||||
|
if (ReadBlock || Console.KeyAvailable)
|
||||||
{
|
{
|
||||||
var result = Console.ReadKey(true);
|
var result = Console.ReadKey(true);
|
||||||
return (byte)result.KeyChar;
|
return (byte)result.KeyChar;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public override void Write(byte val)
|
public override void Write(byte val)
|
||||||
|
{
|
||||||
|
if (Enabled)
|
||||||
{
|
{
|
||||||
Console.Write((char)val);
|
Console.Write((char)val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="PGM\CALL.txt" />
|
<None Remove="PGM\CALL.txt" />
|
||||||
|
<None Remove="PGM\FlagTest.txt" />
|
||||||
<None Remove="PGM\HELLO.txt" />
|
<None Remove="PGM\HELLO.txt" />
|
||||||
<None Remove="PGM\LOGIC.txt" />
|
<None Remove="PGM\LOGIC.txt" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
@@ -17,6 +18,9 @@
|
|||||||
<Content Include="PGM\CALL.txt">
|
<Content Include="PGM\CALL.txt">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Include="PGM\FlagTest.txt">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
<Content Include="PGM\HELLO.txt">
|
<Content Include="PGM\HELLO.txt">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
|||||||
43
SVM/VM.cs
43
SVM/VM.cs
@@ -8,7 +8,7 @@ namespace SVM
|
|||||||
class VM
|
class VM
|
||||||
{
|
{
|
||||||
public const int REGISTERS = 4;
|
public const int REGISTERS = 4;
|
||||||
public const int PORTS = 8;
|
public const int PORTS = 255;
|
||||||
public const int STACKDEPTH = 16;
|
public const int STACKDEPTH = 16;
|
||||||
public const int MEMSIZE = 0xFFFF;
|
public const int MEMSIZE = 0xFFFF;
|
||||||
|
|
||||||
@@ -20,18 +20,23 @@ namespace SVM
|
|||||||
public ushort[] STACK = new ushort[STACKDEPTH];
|
public ushort[] STACK = new ushort[STACKDEPTH];
|
||||||
public byte[] MEM = new byte[MEMSIZE];
|
public byte[] MEM = new byte[MEMSIZE];
|
||||||
public Port[] Ports = new Port[PORTS];
|
public Port[] Ports = new Port[PORTS];
|
||||||
|
public ushort FlagStart = 0xFF00;
|
||||||
|
|
||||||
public int CycleDelay = 0;
|
public int CycleDelay = 0;
|
||||||
|
|
||||||
private Dictionary<byte, Instruction> instructions = new Dictionary<byte, Instruction>();
|
private Dictionary<byte, Instruction> instructions = new Dictionary<byte, Instruction>();
|
||||||
|
private Dictionary<byte, Flag> flags = new Dictionary<byte, Flag>();
|
||||||
|
|
||||||
public VM()
|
public VM()
|
||||||
{
|
{
|
||||||
var instrs = Instruction.GetAllInstructions();
|
foreach(var instr in Instruction.GetAllInstructions())
|
||||||
foreach(var instr in instrs)
|
|
||||||
{
|
{
|
||||||
instructions.Add(instr.OP, instr);
|
instructions.Add(instr.OP, instr);
|
||||||
}
|
}
|
||||||
|
foreach(var flag in Flag.GetAllFlags())
|
||||||
|
{
|
||||||
|
flags.Add(flag.Address, flag);
|
||||||
|
}
|
||||||
|
|
||||||
Ports[0] = new Ports.ConsolePort(this);
|
Ports[0] = new Ports.ConsolePort(this);
|
||||||
Reset();
|
Reset();
|
||||||
@@ -72,11 +77,39 @@ 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.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.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("{0}", instr.ToASM(decoded));
|
||||||
instr.Exec(this, decoded);
|
instr.Exec(this, decoded);
|
||||||
//Console.ReadKey(true);
|
//Console.ReadKey(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte Read(ushort location)
|
||||||
|
{
|
||||||
|
if (location >= FlagStart && location < FlagStart + 0xFF)
|
||||||
|
{
|
||||||
|
byte flagAddress = (byte)(location - FlagStart);
|
||||||
|
if (flags.ContainsKey(flagAddress))
|
||||||
|
{
|
||||||
|
return flags[flagAddress].Read(this);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return MEM[location];
|
||||||
|
}
|
||||||
|
public void Write(ushort location, byte val)
|
||||||
|
{
|
||||||
|
if (location >= FlagStart && location < FlagStart + 0xFF)
|
||||||
|
{
|
||||||
|
byte flagAddress = (byte)(location - FlagStart);
|
||||||
|
if (flags.ContainsKey(flagAddress))
|
||||||
|
{
|
||||||
|
flags[flagAddress].Write(this, val);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
MEM[location] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user