Skip to content

Commit

Permalink
Merge pull request #38 from rbaker26/seq_json
Browse files Browse the repository at this point in the history
Added Addition OpCode Support
  • Loading branch information
rbaker26 authored Jun 17, 2020
2 parents 188d846 + 98ae2ad commit 4a42625
Show file tree
Hide file tree
Showing 20 changed files with 771 additions and 212 deletions.
38 changes: 22 additions & 16 deletions SAP1EMU.Assembler/Assemble.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using SAP1EMU.Lib;
using SAP1EMU.Lib.Components;
using SAP1EMU.Lib.Utilities;

namespace SAP1EMU.Assembler
{
public static class Assemble
{

public static List<string> Parse(List<string> unchecked_assembly)
private const string DefaultInstructionSetName = "SAP1Emu";
public static List<string> Parse(List<string> unchecked_assembly, string InstructionSetName = DefaultInstructionSetName)
{

// Get Instruction Set
InstructionSet iset = OpCodeLoader.GetSet(InstructionSetName);

// *********************************************************************
// Sanitize *
// *********************************************************************
Expand Down Expand Up @@ -60,7 +64,7 @@ public static List<string> Parse(List<string> unchecked_assembly)


//if is not valid, will throw execptions for CLI to catch and display to user
_ = IsValid(unchecked_assembly);
_ = IsValid(unchecked_assembly, iset);
// *********************************************************************


Expand Down Expand Up @@ -96,9 +100,9 @@ public static List<string> Parse(List<string> unchecked_assembly)


// Convert Upper Nibble
if (SEQ.Instance().SupportedCommandsBinTable.ContainsKey(upper_nibble_asm)) // Is instruction
if (InstructionValidator.IsValidInstruction(upper_nibble_asm, iset)) // Is instruction
{
upper_nibble_bin = SEQ.Instance().SupportedCommandsBinTable[line.Substring(0, 3)];
upper_nibble_bin = InstructionValidator.GetUpperNibble(line.Substring(0, 3), iset);
}
else if (Regex.IsMatch(upper_nibble_asm, "^0[xX][0-9a-fA-F]$")) // Is Data
{
Expand All @@ -125,7 +129,7 @@ public static List<string> Parse(List<string> unchecked_assembly)
return binary;
}

private static bool IsValid(List<string> unchecked_assembly)
private static bool IsValid(List<string> unchecked_assembly, InstructionSet iset)
{
bool dot_macro_used = false;

Expand All @@ -138,14 +142,14 @@ private static bool IsValid(List<string> unchecked_assembly)

if(nibbles.Length == 0)
{
throw new ParseException($"SAP1ASM: Line cannot be blank (line: {line_number})", new ParseException("Use \"NOP 0x0\" for a no-operation command"));
throw new ParseException($"SAP1ASM: Line cannot be blank (line: {line_number}).", new ParseException("Use \"NOP 0x0\" for a no-operation command"));

}

string instruction = nibbles[0];
if (nibbles.Length < 2)
{
throw new ParseException($"SAP1ASM: No lower nibble detected (line: {line_number})", new ParseException($"{instruction} must be paired with a valid address in the range of 0x0 - 0xF"));
throw new ParseException($"SAP1ASM: No lower nibble detected (line: {line_number}).", new ParseException($"{instruction} must be paired with a valid address in the range of 0x0 - 0xF"));
}
string addr = nibbles[1];

Expand All @@ -154,13 +158,15 @@ private static bool IsValid(List<string> unchecked_assembly)
// Check Intruction
if (instruction.Length != 3)
{
throw new ParseException($"SAP1ASM: invalid intruction on line {line_number}", new ParseException($"{instruction} is not a recognized instruction"));
throw new ParseException($"SAP1ASM: invalid intruction on line {line_number}.", new ParseException($"{instruction} is not a recognized instruction"));
}
if (!SEQ.Instance().SupportedCommandsBinTable.ContainsKey(instruction.ToUpper())) // Check if is valid instruction


if (!InstructionValidator.IsValidInstruction(instruction.ToUpper(),iset)) // Check if is valid instruction
{
if (!Regex.IsMatch(instruction, "^0[xX][0-9a-fA-F]$")) // Make sure it isnt data
{
throw new ParseException($"SAP1ASM: invalid intruction on line {line_number}", new ParseException($"{instruction} is not a recognized instruction or valid data"));
throw new ParseException($"SAP1ASM: invalid intruction on line {line_number}.", new ParseException($"{instruction} is not a recognized instruction or valid data"));
}
}

Expand All @@ -169,21 +175,21 @@ private static bool IsValid(List<string> unchecked_assembly)
// Check Address
if (addr.Length != 3) // should be no more than 3
{
throw new ParseException($"SAP1ASM: invalid address on line {line_number}", new ParseException($"{addr} is not of the form \"0xX\""));
throw new ParseException($"SAP1ASM: invalid address on line {line_number}.", new ParseException($"{addr} is not of the form \"0xX\""));
}
if (!Regex.IsMatch(addr, "^0[xX][0-9a-fA-F]$")) // should be of the form 0xX
{
throw new ParseException($"SAP1ASM: invalid address on line {line_number}", new ParseException($"{addr} is not of the form \"0xX\""));
throw new ParseException($"SAP1ASM: invalid address on line {line_number}.", new ParseException($"{addr} is not of the form \"0xX\""));
}
int hex_addr = (int)(Convert.ToUInt32(addr.Substring(2, 1), 16));
if (hex_addr < 0 || hex_addr >= 16) // must tbe between 0-15
{
throw new ParseException($"SAP1ASM: address out of range on line {line_number}", new ParseException($"{addr} must be betweeen 0x0 and 0xF"));
throw new ParseException($"SAP1ASM: address out of range on line {line_number}.", new ParseException($"{addr} must be betweeen 0x0 and 0xF"));
}

if(line.Contains("..."))
{
throw new ParseException($"SAP1ASM: invalid use of \"...\" on line {line_number}", new ParseException($"{line} must only contain \"...\" with no extra charecters or spaces"));
throw new ParseException($"SAP1ASM: invalid use of \"...\" on line {line_number}.", new ParseException($"{line} must only contain \"...\" with no extra charecters or spaces"));

}
}
Expand All @@ -195,7 +201,7 @@ private static bool IsValid(List<string> unchecked_assembly)
}
else
{
throw new ParseException($"SAP1ASM: invalid use of \"...\" {line_number}", new ParseException($"{line} must only contain once instance of \"...\" in the program"));
throw new ParseException($"SAP1ASM: invalid use of \"...\" {line_number}.", new ParseException($"{line} must only contain once instance of \"...\" in the program"));

}
}
Expand Down
35 changes: 35 additions & 0 deletions SAP1EMU.Assembler/InstructionValidator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Text;

using SAP1EMU.Lib;

namespace SAP1EMU.Assembler
{
public class InstructionValidator
{
public static bool IsValidInstruction(string instruction, InstructionSet iset)
{
if(instruction.ToLower() == "nop")
{
return true;
}
try
{
return !string.IsNullOrEmpty(iset.instructions.Find(x => x.OpCode.ToLower().Equals(instruction.ToLower())).OpCode);
}
catch(NullReferenceException)
{
return false;
}
}
public static string GetUpperNibble(string instruction, InstructionSet iset)
{
if (instruction.ToLower() == "nop")
{
return "0000";
}
return iset.instructions.Find(x => x.OpCode.ToLower().Equals(instruction.ToLower())).BinCode;
}
}
}
1 change: 1 addition & 0 deletions SAP1EMU.Assembler/SAP1EMU.Assembler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\SAP1EMU.Engine\SAP1EMU.Engine.csproj" />
<ProjectReference Include="..\SAP1EMU.Lib\SAP1EMU.Lib.csproj" />
</ItemGroup>

Expand Down
98 changes: 75 additions & 23 deletions SAP1EMU.Engine-CLI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
using System.IO;
using System.Text;
using System.Threading;

using CommandLine;

using SAP1EMU.Assembler;
using SAP1EMU.Engine;
using SAP1EMU.Lib;
Expand All @@ -24,13 +26,13 @@ public class Options
// ********************************************



// Verbosity **********************************
[Option('v', "verbose", Required = false, HelpText = "Set output to verbose.\n(inlcudes debug statements from the engine)")]
public bool Verbose { get; set; }
[Option('V', "very-verbose", Required = false, HelpText = "Set output to very verbose.\n(includes debug statements from the engine and the input file in output)")]
public bool VeryVerbose { get; set; }
// ********************************************
// TODO - Figure out if I want to use these
//// Verbosity **********************************
//[Option('v', "verbose", Required = false, HelpText = "Set output to verbose.\n(inlcudes debug statements from the engine)")]
//public bool Verbose { get; set; }
//[Option('V', "very-verbose", Required = false, HelpText = "Set output to very verbose.\n(includes debug statements from the engine and the input file in output)")]
//public bool VeryVerbose { get; set; }
//// ********************************************


// Frame Support ******************************
Expand All @@ -44,7 +46,7 @@ public class Options

// TODO - Figure out why default isnt working here
// Default should be "std"
[Option('O', "FOframe", SetName = "FOframe", Required = false, HelpText = "Include Snapshots of the Output Register in the output file.\nParameters:\n std\t\tOutputs with formatting\n no-format\tOutputs wil no formatting")]
[Option('O', "FOfragitme", SetName = "FOframe", Required = false, HelpText = "Include Snapshots of the Output Register in the output file.\nParameters:\n std\t\tOutputs with formatting\n no-format\tOutputs wil no formatting")]
public string FOframe { get; set; }
// ********************************************

Expand All @@ -53,6 +55,12 @@ public class Options
public bool Debug { get; set; }
// ********************************************

// Instruction Set ****************************
[Option('i', "instructionSet", Required = false, HelpText = "Sets the Instruction Set to use\nParameters:\n SAP1Emu\tUses expanded SAP1EMU Instruction Set (default)\n Malvino\tUses Malvino's Instruction Set\n BenEater\tUses Ben Eater's Instruction Set", Default = "SAP1Emu")]
public string InstructionSetName { get; set; }
// ********************************************




}
Expand Down Expand Up @@ -124,24 +132,58 @@ static void Main(string[] args)


}
if(!string.IsNullOrEmpty(o.FOframe))
if (!string.IsNullOrEmpty(o.FOframe))
{
if (o.FOframe.ToLower() != "no-format" && o.FOframe.ToLower() != "std")
{
Console.Error.WriteLine($"SAP1EMU: warning: {o.SourceFile}: invalid format argument {o.FOframe}: Defaulting to \"std\".");
o.FOframe = "std";
}
}



if (o.InstructionSetName.ToLower() != "sap1emu" && o.InstructionSetName.ToLower() != "malvino" && o.InstructionSetName.ToLower() != "beneater")
{
Console.Error.WriteLine($"SAP1EMU: warning: {o.InstructionSetName}: invalid argument: Defaulting to \"SAP1Emu\".");
o.InstructionSetName = "SAP1Emu";
}


List<string> compiled_binary;




List<string> compiled_binary = null;

if (fileType == FileType.S)
{
compiled_binary = Assemble.Parse(source_file_contents);
try
{
compiled_binary = Assemble.Parse(source_file_contents, o.InstructionSetName);
}
catch (ParseException pe)
{
//Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));
//Console.SetError(new StreamWriter(Console.OpenStandardError()));

var tempColor = Console.ForegroundColor;
if (Console.BackgroundColor == ConsoleColor.Red)
{
Console.ForegroundColor = ConsoleColor.Cyan;
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
}
Console.Error.WriteLine($"SAP1ASM: fatal error: " + pe.Message + " " + pe.InnerException.Message);
Console.ForegroundColor = tempColor;
Console.Error.WriteLine("assembly terminated");



Console.Error.Flush();

System.Environment.Exit(1);
}
}
else
{
Expand All @@ -164,18 +206,28 @@ static void Main(string[] args)
//Console.SetError(writer_error);


engine.Init(rmp);
engine.Init(rmp, o.InstructionSetName);
try
{
engine.Run();

}
catch (EngineRuntimeException ere)
{
Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));
Console.SetError(new StreamWriter(Console.OpenStandardError()));
var tempColor = Console.ForegroundColor;
if (Console.BackgroundColor == ConsoleColor.Red)
{
Console.ForegroundColor = ConsoleColor.Cyan;
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
}
//Console.SetOut(new StreamWriter(Console.OpenStandardOutput()));
//Console.SetError(new StreamWriter(Console.OpenStandardError()));

Console.Error.WriteLine($"SAP1EMU: fatal error: " + ere.Message);
Console.Error.WriteLine($"SAP1EMU: fatal error: " + ere.Message + " " + ere.InnerException.Message);
Console.ForegroundColor = tempColor;
Console.Error.WriteLine("emulation terminated");

Console.Error.Flush();
Expand All @@ -186,7 +238,7 @@ static void Main(string[] args)


string engine_output = "************************************************************\n"
+ "Final Output Register Value: " + engine.GetOutput()
+ "Final Output Register Value: " + engine.GetOutputReg()
+ "\n************************************************************\n\n";

List<Frame> FrameStack = engine.FrameStack();
Expand All @@ -208,9 +260,9 @@ static void Main(string[] args)

engine_output += "\n" + sb.ToString();
}
else if(o.FOframe != null)
else if (o.FOframe != null)
{
engine_output =null; // Clear the output
engine_output = null; // Clear the output

StringBuilder sb = new StringBuilder();
StringWriter fw = new StringWriter(sb);
Expand All @@ -223,16 +275,16 @@ static void Main(string[] args)
{
fw.WriteLine(frame.OutputRegister());
}
else if(o.FOframe.ToLower() == "no-format")
else if (o.FOframe.ToLower() == "no-format")
{
string temp = frame.OReg;
if(string.IsNullOrEmpty(temp))
if (string.IsNullOrEmpty(temp))
{
temp = "00000000";
}
fw.WriteLine(temp);
}

}
}
fw.Flush();
Expand Down
Loading

0 comments on commit 4a42625

Please sign in to comment.