From 9bd3acb6b4f9c045bdb00ed3d7c37a498d69e64c Mon Sep 17 00:00:00 2001 From: TollyH Date: Sat, 4 May 2024 20:28:25 +0100 Subject: [PATCH] Conditional compilation of extension sets --- AAPFile.cs | 51 +++++++++++- AssEmbly.csproj | 4 + Assembler.cs | 56 +++++++++++++ Data.cs | 37 ++++++++- Debugger.cs | 28 ++++++- Exceptions.cs | 4 + Processor.cs | 195 ++++++++++++++++++++++++++++++++++++++++------ Program.Shared.cs | 11 ++- Program.cs | 60 ++++++++++++-- 9 files changed, 406 insertions(+), 40 deletions(-) diff --git a/AAPFile.cs b/AAPFile.cs index e9826df..8bb15ca 100644 --- a/AAPFile.cs +++ b/AAPFile.cs @@ -8,26 +8,63 @@ namespace AssEmbly public enum AAPFeatures : ulong { None = 0, +#if V1_CALL_STACK_COMPAT V1CallStack = 0b1, +#endif +#if EXTENSION_SET_SIGNED ExtensionSigned = 0b10, +#endif +#if EXTENSION_SET_FLOATING_POINT ExtensionFloat = 0b100, +#endif +#if EXTENSION_SET_EXTENDED_BASE ExtensionExtendedBase = 0b1000, +#endif +#if GZIP_COMPRESSION GZipCompressed = 0b10000, +#endif +#if EXTENSION_SET_EXTERNAL_ASM ExtensionExternalAssembly = 0b100000, +#endif +#if EXTENSION_SET_HEAP_ALLOCATE ExtensionMemoryAllocation = 0b1000000, +#endif +#if EXTENSION_SET_FILE_SYSTEM ExtensionFileSystem = 0b10000000, +#endif +#if EXTENSION_SET_TERMINAL ExtensionTerminal = 0b100000000, +#endif - All = V1CallStack + All = None +#if V1_CALL_STACK_COMPAT + | V1CallStack +#endif +#if EXTENSION_SET_SIGNED | ExtensionSigned +#endif +#if EXTENSION_SET_FLOATING_POINT | ExtensionFloat +#endif +#if EXTENSION_SET_EXTENDED_BASE | ExtensionExtendedBase +#endif +#if GZIP_COMPRESSION | GZipCompressed +#endif +#if EXTENSION_SET_EXTERNAL_ASM | ExtensionExternalAssembly +#endif +#if EXTENSION_SET_HEAP_ALLOCATE | ExtensionMemoryAllocation +#endif +#if EXTENSION_SET_FILE_SYSTEM | ExtensionFileSystem - | ExtensionTerminal, - Incompatible = ~All +#endif +#if EXTENSION_SET_TERMINAL + | ExtensionTerminal +#endif + , Incompatible = ~All } public class AAPFile @@ -71,6 +108,7 @@ public AAPFile(byte[] executable) Features = (AAPFeatures)BinaryPrimitives.ReadUInt64LittleEndian(byteSpan[20..]); EntryPoint = BinaryPrimitives.ReadUInt64LittleEndian(byteSpan[28..]); +#if GZIP_COMPRESSION if (Features.HasFlag(AAPFeatures.GZipCompressed)) { using MemoryStream compressedProgram = new(executable[36..]); @@ -81,13 +119,17 @@ public AAPFile(byte[] executable) } else { +#endif Program = executable[36..]; +#if GZIP_COMPRESSION } +#endif } public byte[] GetBytes() { byte[] programBytes; +#if GZIP_COMPRESSION if (Features.HasFlag(AAPFeatures.GZipCompressed)) { using MemoryStream compressedProgram = new(); @@ -99,8 +141,11 @@ public byte[] GetBytes() } else { +#endif programBytes = Program; +#if GZIP_COMPRESSION } +#endif byte[] bytes = new byte[HeaderSize + programBytes.Length]; Span byteSpan = bytes.AsSpan(); diff --git a/AssEmbly.csproj b/AssEmbly.csproj index dab7cff..6e2a1d1 100644 --- a/AssEmbly.csproj +++ b/AssEmbly.csproj @@ -15,6 +15,10 @@ True + + $(DefineConstants);V1_CALL_STACK_COMPAT;EXTENSION_SET_SIGNED;EXTENSION_SET_FLOATING_POINT;EXTENSION_SET_EXTENDED_BASE;GZIP_COMPRESSION;EXTENSION_SET_EXTERNAL_ASM;EXTENSION_SET_HEAP_ALLOCATE;EXTENSION_SET_FILE_SYSTEM;EXTENSION_SET_TERMINAL; + + diff --git a/Assembler.cs b/Assembler.cs index 98f4e04..5f11d8e 100644 --- a/Assembler.cs +++ b/Assembler.cs @@ -196,6 +196,62 @@ public Assembler(bool usingV1Format, bool usingV1Stack, { "CURRENT_ADDRESS", () => (ulong)program.Count }, { "OBSOLETE_DIRECTIVES", () => EnableObsoleteDirectives ? 1UL : 0UL }, { "ESCAPE_SEQUENCES", () => EnableEscapeSequences ? 1UL : 0UL }, + { + "EXTENSION_SET_SIGNED_AVAIL", () => +#if EXTENSION_SET_SIGNED + 1 +#else + 0 +#endif + }, + { + "EXTENSION_SET_FLOATING_POINT_AVAIL", () => +#if EXTENSION_SET_FLOATING_POINT + 1 +#else + 0 +#endif + }, + { + "EXTENSION_SET_EXTENDED_BASE_AVAIL", () => +#if EXTENSION_SET_EXTENDED_BASE + 1 +#else + 0 +#endif + }, + { + "EXTENSION_SET_EXTERNAL_ASM_AVAIL", () => +#if EXTENSION_SET_EXTERNAL_ASM + 1 +#else + 0 +#endif + }, + { + "EXTENSION_SET_HEAP_ALLOCATE_AVAIL", () => +#if EXTENSION_SET_HEAP_ALLOCATE + 1 +#else + 0 +#endif + }, + { + "EXTENSION_SET_FILE_SYSTEM_AVAIL", () => +#if EXTENSION_SET_FILE_SYSTEM + 1 +#else + 0 +#endif + }, + { + "EXTENSION_SET_TERMINAL_AVAIL", () => +#if EXTENSION_SET_TERMINAL + 1 +#else + 0 +#endif + }, }; InitializeStateDirectives(out stateDirectives, out obsoleteStateDirectives); diff --git a/Data.cs b/Data.cs index edea8b2..48fa8e7 100644 --- a/Data.cs +++ b/Data.cs @@ -31,19 +31,22 @@ public enum Register [Flags] public enum StatusFlags { - // Base Zero = 0b1, Carry = 0b10, FileEnd = 0b100, - // Signed +#if EXTENSION_SET_SIGNED Sign = 0b1000, Overflow = 0b10000, +#endif +#if EXTENSION_SET_TERMINAL AutoEcho = 0b100000, +#endif - // Base ZeroAndCarry = Zero | Carry, +#if EXTENSION_SET_SIGNED // Signed SignAndOverflow = Sign | Overflow, +#endif } /// @@ -53,13 +56,27 @@ public static class Data { public static readonly Dictionary ExtensionSetFeatureFlags = new() { +#if EXTENSION_SET_SIGNED { 0x01, AAPFeatures.ExtensionSigned }, +#endif +#if EXTENSION_SET_FLOATING_POINT { 0x02, AAPFeatures.ExtensionFloat }, +#endif +#if EXTENSION_SET_EXTENDED_BASE { 0x03, AAPFeatures.ExtensionExtendedBase }, +#endif +#if EXTENSION_SET_EXTERNAL_ASM { 0x04, AAPFeatures.ExtensionExternalAssembly }, +#endif +#if EXTENSION_SET_HEAP_ALLOCATE { 0x05, AAPFeatures.ExtensionMemoryAllocation }, +#endif +#if EXTENSION_SET_FILE_SYSTEM { 0x06, AAPFeatures.ExtensionFileSystem }, +#endif +#if EXTENSION_SET_TERMINAL { 0x07, AAPFeatures.ExtensionTerminal }, +#endif }; /// @@ -350,6 +367,7 @@ public static class Data // RFC (Read Character from Open File as a Byte) { ("RFC", new OperandType[1] { OperandType.Register }), new Opcode(0x00, 0xF1) }, +#if EXTENSION_SET_SIGNED // SIGNED EXTENSION SET // Signed Conditional Jumps @@ -458,7 +476,9 @@ public static class Data // SIGN_NEG (Two's Complement Negation) { ("SIGN_NEG", new OperandType[1] { OperandType.Register }), new Opcode(0x01, 0x80) }, +#endif +#if EXTENSION_SET_FLOATING_POINT // FLOATING POINT EXTENSION SET // Math (All operations store result in the first register operand) @@ -575,7 +595,9 @@ public static class Data { ("FLPT_CMP", new OperandType[2] { OperandType.Register, OperandType.Literal }), new Opcode(0x02, 0xD1) }, // (reg - lit) { ("FLPT_CMP", new OperandType[2] { OperandType.Register, OperandType.Address }), new Opcode(0x02, 0xD2) }, // (reg - adr) { ("FLPT_CMP", new OperandType[2] { OperandType.Register, OperandType.Pointer }), new Opcode(0x02, 0xD3) }, // (reg - ptr) +#endif +#if EXTENSION_SET_EXTENDED_BASE // EXTENDED BASE SET // EXTD_BSW (Reverse Byte Order) @@ -601,7 +623,9 @@ public static class Data { ("EXTD_MPA", new OperandType[2] { OperandType.Register, OperandType.Pointer }), new Opcode(0x03, 0x30) }, { ("EXTD_MPA", new OperandType[2] { OperandType.Address, OperandType.Pointer }), new Opcode(0x03, 0x31) }, { ("EXTD_MPA", new OperandType[2] { OperandType.Pointer, OperandType.Pointer }), new Opcode(0x03, 0x32) }, +#endif +#if EXTENSION_SET_EXTERNAL_ASM // EXTERNAL ASSEMBLY EXTENSION SET // ASMX_LDA (Load Assembly) @@ -632,7 +656,9 @@ public static class Data { ("ASMX_CAL", new OperandType[1] { OperandType.Literal }), new Opcode(0x04, 0x32) }, { ("ASMX_CAL", new OperandType[1] { OperandType.Address }), new Opcode(0x04, 0x33) }, { ("ASMX_CAL", new OperandType[1] { OperandType.Pointer }), new Opcode(0x04, 0x34) }, +#endif +#if EXTENSION_SET_HEAP_ALLOCATE // MEMORY ALLOCATION EXTENSION SET // HEAP_ALC (Allocate Heap Memory - Error if Fail) @@ -661,7 +687,9 @@ public static class Data // HEAP_FRE (Free Allocated Heap Memory) { ("HEAP_FRE", new OperandType[1] { OperandType.Register }), new Opcode(0x05, 0x20) }, +#endif +#if EXTENSION_SET_FILE_SYSTEM // FILE SYSTEM EXTENSION SET // FSYS_CWD (Change Working Directory to Path Specified by 0x00 Terminated String in Memory) @@ -742,7 +770,9 @@ public static class Data { ("FSYS_SAT", new OperandType[2] { OperandType.Pointer, OperandType.Register }), new Opcode(0x06, 0x89) }, { ("FSYS_SAT", new OperandType[2] { OperandType.Address, OperandType.Literal }), new Opcode(0x06, 0x8A) }, { ("FSYS_SAT", new OperandType[2] { OperandType.Pointer, OperandType.Literal }), new Opcode(0x06, 0x8B) }, +#endif +#if EXTENSION_SET_TERMINAL // TERMINAL EXTENSION SET // TERM_CLS (Clear Screen) @@ -795,6 +825,7 @@ public static class Data // TERM_RSC (Reset Color) { ("TERM_RSC", Array.Empty()), new Opcode(0x07, 0x58) }, +#endif }; /// diff --git a/Debugger.cs b/Debugger.cs index cf6f2d1..9eef327 100644 --- a/Debugger.cs +++ b/Debugger.cs @@ -18,11 +18,18 @@ public class Debugger public List<(Register Register, ulong Value)> Breakpoints { get; } = new(); +#if V1_CALL_STACK_COMPAT public bool UseV1CallStack => DebuggingProcessor.UseV1CallStack; private ulong stackCallSize => UseV1CallStack ? 24UL : 16UL; - private Register[] registerPushOrder => UseV1CallStack - ? new Register[3] { Register.rso, Register.rsb, Register.rpo } - : new Register[2] { Register.rsb, Register.rpo }; +#else + private const ulong stackCallSize = 16; +#endif + + private Register[] registerPushOrder => +#if V1_CALL_STACK_COMPAT + UseV1CallStack ? new Register[3] { Register.rso, Register.rsb, Register.rpo } : +#endif + new Register[2] { Register.rsb, Register.rpo }; private readonly ulong[] replPreviousRegisters = new ulong[Enum.GetNames(typeof(Register)).Length]; private readonly Dictionary replLabels = new() { { "START", 0 } }; @@ -286,9 +293,11 @@ public void StartDebugger() case "breakpoint": CommandBreakpointManage(command); break; +#if EXTENSION_SET_HEAP_ALLOCATE case "heap": CommandHeapStats(); break; +#endif case "help": CommandDebugHelp(); break; @@ -513,11 +522,13 @@ private void CommandMapMemory(string[] command) for (ulong i = rowStartAdr; i < rowStartAdr + 16; i++) { string valueStr = string.Format(Strings.Debugger_MemoryMap_Cell, DebuggingProcessor.Memory[i]); +#if EXTENSION_SET_HEAP_ALLOCATE // Being unmapped is the lowest priority colour, and should be completely replaced by any register colours if (DebuggingProcessor.MappedMemoryRanges.All(mappedRange => !mappedRange.Contains((long)i))) { Console.ForegroundColor = ConsoleColor.DarkGray; } +#endif // Write both characters separately so that if multiple registers point to the same address, the cell becomes multi-coloured if (i == DebuggingProcessor.Registers[(int)Register.rso]) { @@ -649,13 +660,20 @@ private void CommandFormatStack(string[] command) Console.WriteLine(Strings.Debugger_Stack_Box_Top); Console.WriteLine(Strings.Debugger_Stack_ReturnInfo_First, currentStackBase, registerPushOrder[0], DebuggingProcessor.ReadMemoryQWord(currentStackBase)); Console.WriteLine(Strings.Debugger_Stack_ReturnInfo_Second, currentStackBase + 8, registerPushOrder[1], DebuggingProcessor.ReadMemoryQWord(currentStackBase + 8)); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { Console.WriteLine(Strings.Debugger_Stack_ReturnInfo_Third, currentStackBase + 16, registerPushOrder[2], DebuggingProcessor.ReadMemoryQWord(currentStackBase + 16)); } +#endif Console.WriteLine(Strings.Debugger_Stack_Box_Bottom); - ulong parentStackBase = DebuggingProcessor.ReadMemoryQWord(currentStackBase + (UseV1CallStack ? 8UL : 0UL)); + ulong parentStackBase = DebuggingProcessor.ReadMemoryQWord(currentStackBase +#if V1_CALL_STACK_COMPAT + + (UseV1CallStack ? 8UL : 0UL) +#endif + ); + if (currentStackBase + stackCallSize >= parentStackBase) { // Parent stack is empty @@ -798,6 +816,7 @@ private void CommandBreakpointManage(string[] command) } } +#if EXTENSION_SET_HEAP_ALLOCATE private void CommandHeapStats() { long memorySize = DebuggingProcessor.Memory.LongLength; @@ -877,6 +896,7 @@ private void CommandHeapStats() } Console.WriteLine(); } +#endif private static void CommandDebugHelp() { diff --git a/Exceptions.cs b/Exceptions.cs index f32561f..4053733 100644 --- a/Exceptions.cs +++ b/Exceptions.cs @@ -227,6 +227,7 @@ public FileOperationException(string message, string consoleMessage) : base(mess public FileOperationException(string message, string consoleMessage, Exception inner) : base(message, consoleMessage, inner) { } } +#if EXTENSION_SET_EXTERNAL_ASM /// /// The exception that is thrown when an external assembly is invalid or could not be found. /// @@ -263,7 +264,9 @@ public ExternalOperationException(string message, Exception inner) : base(messag public ExternalOperationException(string message, string consoleMessage) : base(message, consoleMessage) { } public ExternalOperationException(string message, string consoleMessage, Exception inner) : base(message, consoleMessage, inner) { } } +#endif +#if EXTENSION_SET_HEAP_ALLOCATE /// /// The exception that is thrown when there is not enough free memory remaining to perform the requested allocation. /// @@ -299,6 +302,7 @@ public InvalidMemoryBlockException(string message, Exception inner) : base(messa public InvalidMemoryBlockException(string message, string consoleMessage) : base(message, consoleMessage) { } public InvalidMemoryBlockException(string message, string consoleMessage, Exception inner) : base(message, consoleMessage, inner) { } } +#endif // AAP FORMAT EXCEPTIONS /// diff --git a/Processor.cs b/Processor.cs index d6ec2c8..b017e90 100644 --- a/Processor.cs +++ b/Processor.cs @@ -13,41 +13,72 @@ namespace AssEmbly /// public class Processor : IDisposable { +#if EXTENSION_SET_EXTERNAL_ASM public static readonly Type[] ExternalMethodParamTypes = new Type[3] { typeof(byte[]), typeof(ulong[]), typeof(ulong?) }; +#endif public static readonly DateTime UnixEpoch = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public readonly byte[] Memory; public readonly ulong[] Registers; +#if V1_CALL_STACK_COMPAT public readonly bool UseV1CallStack; +#endif +#if EXTENSION_SET_HEAP_ALLOCATE public readonly bool MapStack; +#endif +#if !EXTENSION_SET_TERMINAL + public readonly bool AutoEcho; +#endif +#if V1_CALL_STACK_COMPAT private readonly ulong stackCallSize; +#else + private const ulong stackCallSize = 16; +#endif +#if EXTENSION_SET_HEAP_ALLOCATE private readonly List _mappedMemoryRanges = new(); public IReadOnlyList MappedMemoryRanges => _mappedMemoryRanges.AsReadOnly(); +#endif public bool ProgramLoaded { get; private set; } public bool IsFileOpen => openFile is not null || fileRead is not null || fileWrite is not null; +#if EXTENSION_SET_EXTERNAL_ASM public bool IsExternalOpen => openExtAssembly is not null || openExtFunction is not null || extLoadContext is not null; +#endif +#if EXTENSION_SET_HEAP_ALLOCATE public bool AnyRegionsMapped => _mappedMemoryRanges.Count > 2; - - public bool IsClean => !IsFileOpen && !IsExternalOpen && !AnyRegionsMapped; +#endif + + public bool IsClean => + !IsFileOpen +#if EXTENSION_SET_EXTERNAL_ASM + && !IsExternalOpen +#endif +#if EXTENSION_SET_HEAP_ALLOCATE + && !AnyRegionsMapped +#endif + ; private Stream? openFile; private BinaryReader? fileRead; private BinaryWriter? fileWrite; private long openFileSize; +#if EXTENSION_SET_EXTERNAL_ASM private AssemblyLoadContext? extLoadContext; private Type? openExtAssembly; private MethodInfo? openExtFunction; +#endif +#if EXTENSION_SET_FILE_SYSTEM private IEnumerator directoryListing = Enumerable.Empty().GetEnumerator(); private IEnumerator fileListing = Enumerable.Empty().GetEnumerator(); +#endif private readonly Random rng = new(); @@ -66,17 +97,27 @@ public Processor(ulong memorySize, ulong entryPoint = 0, Registers[(int)Register.rpo] = entryPoint; Registers[(int)Register.rso] = memorySize; Registers[(int)Register.rsb] = memorySize; +#if EXTENSION_SET_HEAP_ALLOCATE _mappedMemoryRanges.Add(new Range((long)memorySize, (long)memorySize)); +#endif ProgramLoaded = false; // AssEmbly stores strings as UTF-8, so console must be set to UTF-8 to render bytes correctly Console.OutputEncoding = Encoding.UTF8; +#if V1_CALL_STACK_COMPAT UseV1CallStack = useV1CallStack; stackCallSize = useV1CallStack ? 24UL : 16UL; +#endif +#if EXTENSION_SET_HEAP_ALLOCATE MapStack = mapStack; +#endif +#if EXTENSION_SET_TERMINAL if (autoEcho) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.AutoEcho; } +#else + AutoEcho = autoEcho; +#endif } ~Processor() @@ -86,10 +127,12 @@ public Processor(ulong memorySize, ulong entryPoint = 0, public void Dispose() { +#if EXTENSION_SET_EXTERNAL_ASM extLoadContext?.Unload(); extLoadContext = null; openExtAssembly = null; openExtFunction = null; +#endif openFile?.Dispose(); openFile = null; @@ -98,8 +141,10 @@ public void Dispose() fileWrite?.Dispose(); fileWrite = null; +#if EXTENSION_SET_FILE_SYSTEM directoryListing.Dispose(); fileListing.Dispose(); +#endif GC.SuppressFinalize(this); } @@ -123,7 +168,9 @@ public void LoadProgram(byte[] programData) throw new InvalidOperationException(string.Format(Strings.Processor_Error_Program_Too_Large, Memory.LongLength, programData.LongLength)); } Array.Copy(programData, Memory, programData.LongLength); +#if EXTENSION_SET_HEAP_ALLOCATE _mappedMemoryRanges.Insert(0, new Range(0, programData.LongLength)); +#endif ProgramLoaded = true; } @@ -179,24 +226,32 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) byte opcodeLow = (byte)(0x0F & opcode); ulong operandStart = ++Registers[(int)Register.rpo]; +#if EXTENSION_SET_HEAP_ALLOCATE ulong oldSO = Registers[(int)Register.rso]; +#endif // Local variables used to hold additional state information while executing instructions ulong initial; ulong mathend; ulong result; ulong remainder; - ulong initialSign; - ulong resultSign; int shiftAmount; string filepath; - string destination; +#if EXTENSION_SET_SIGNED + ulong initialSign; + ulong resultSign; long signedInitial; long signedMathend; ulong signedShiftAllBits; +#endif +#if EXTENSION_SET_FLOATING_POINT double floatingInitial; double floatingMathend; double floatingResult; +#endif +#if EXTENSION_SET_FILE_SYSTEM + string destination; +#endif switch (extensionSet) { @@ -380,6 +435,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED initialSign = initial & SignBit; resultSign = result & SignBit; if (initialSign == (mathend & SignBit) && initialSign != resultSign) @@ -399,6 +455,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (result == 0) { @@ -448,6 +505,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED initialSign = initial & SignBit; resultSign = result & SignBit; if (initialSign != (mathend & SignBit) && initialSign != resultSign) @@ -467,6 +525,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (result == 0) { @@ -503,8 +562,6 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) result = initial * mathend; WriteMemoryRegister(operandStart, result); - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; - if (result < initial && mathend != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Carry; @@ -514,6 +571,10 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } + +#if EXTENSION_SET_SIGNED + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -531,6 +592,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Zero; } +#endif break; case 0x40: // Division initial = ReadMemoryRegister(operandStart); @@ -602,6 +664,8 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; + +#if EXTENSION_SET_SIGNED Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if ((result & SignBit) != 0) @@ -612,6 +676,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (result == 0) { @@ -707,6 +772,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Zero; } +#if EXTENSION_SET_SIGNED if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -717,6 +783,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) } Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; +#endif break; case 0x60: // Bitwise initial = ReadMemoryRegister(operandStart); @@ -784,7 +851,6 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if (result == 0) { @@ -795,6 +861,9 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Zero; } +#if EXTENSION_SET_SIGNED + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -803,6 +872,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif break; case 0x70: // Test initial = ReadMemoryRegister(operandStart); @@ -856,6 +926,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED initialSign = initial & SignBit; resultSign = result & SignBit; if (initialSign != (mathend & SignBit) && initialSign != resultSign) @@ -866,13 +937,17 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; } +#endif } else { result = initial & mathend; +#if EXTENSION_SET_SIGNED resultSign = result & SignBit; +#endif } +#if EXTENSION_SET_SIGNED if (resultSign != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -881,6 +956,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (result == 0) { @@ -1071,10 +1147,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) case 0x0: // CAL adr WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 8); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryQWord(operandStart); @@ -1082,10 +1160,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) case 0x1: // CAL ptr WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 1); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryRegister(operandStart); @@ -1094,10 +1174,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryRegister(operandStart + 8); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 9); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryQWord(operandStart); @@ -1106,10 +1188,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryQWord(operandStart + 8); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 16); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryQWord(operandStart); @@ -1118,10 +1202,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryPointedQWord(operandStart + 8); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 16); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryQWord(operandStart); @@ -1130,10 +1216,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryRegisterPointedQWord(operandStart + 8); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 9); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryQWord(operandStart); @@ -1142,10 +1230,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryRegister(operandStart + 1); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 2); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryRegister(operandStart); @@ -1154,10 +1244,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryQWord(operandStart + 1); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 9); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryRegister(operandStart); @@ -1166,10 +1258,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryPointedQWord(operandStart + 1); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 9); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryRegister(operandStart); @@ -1178,10 +1272,12 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) Registers[(int)Register.rfp] = ReadMemoryRegisterPointedQWord(operandStart + 1); WriteMemoryQWord(Registers[(int)Register.rso] - 8, operandStart + 2); WriteMemoryQWord(Registers[(int)Register.rso] - 16, Registers[(int)Register.rsb]); +#if V1_CALL_STACK_COMPAT if (UseV1CallStack) { WriteMemoryQWord(Registers[(int)Register.rso] - 24, Registers[(int)Register.rso]); } +#endif Registers[(int)Register.rso] -= stackCallSize; Registers[(int)Register.rsb] = Registers[(int)Register.rso]; Registers[(int)Register.rpo] = ReadMemoryRegister(operandStart); @@ -1499,7 +1595,11 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) } } } +#if EXTENSION_SET_TERMINAL if ((Registers[(int)Register.rsf] & (ulong)StatusFlags.AutoEcho) != 0) +#else + if (AutoEcho) +#endif { // Echo byte to console stdout.WriteByte(currentByte); @@ -1533,6 +1633,7 @@ public bool Execute(bool runUntilHalt, Stream? stdoutOverride = null) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_Base, opcodeHigh)); } break; +#if EXTENSION_SET_SIGNED case 0x01: // Signed extension set switch (opcodeHigh) { @@ -2103,6 +2204,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_Signed, opcodeHigh)); } break; +#endif +#if EXTENSION_SET_FLOATING_POINT case 0x2: // Floating point extension set switch (opcodeHigh) { @@ -2133,8 +2236,6 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) result = BitConverter.DoubleToUInt64Bits(floatingResult); WriteMemoryRegister(operandStart, result); - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; - if (floatingResult < floatingInitial) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Carry; @@ -2144,6 +2245,9 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -2152,6 +2256,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2189,8 +2294,6 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) result = BitConverter.DoubleToUInt64Bits(floatingResult); WriteMemoryRegister(operandStart, result); - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; - if (floatingResult > floatingInitial) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Carry; @@ -2200,6 +2303,9 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -2208,6 +2314,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2245,8 +2352,6 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) result = BitConverter.DoubleToUInt64Bits(floatingResult); WriteMemoryRegister(operandStart, result); - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; - if (floatingResult < floatingInitial) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Carry; @@ -2256,6 +2361,9 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -2264,6 +2372,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2345,6 +2454,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; + +#if EXTENSION_SET_SIGNED Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if ((result & SignBit) != 0) @@ -2355,6 +2466,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2416,6 +2528,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; + +#if EXTENSION_SET_SIGNED Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if ((result & SignBit) != 0) @@ -2426,6 +2540,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2463,8 +2578,6 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) result = BitConverter.DoubleToUInt64Bits(floatingResult); WriteMemoryRegister(operandStart, result); - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; - if (floatingResult < floatingInitial) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Carry; @@ -2474,6 +2587,9 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -2482,6 +2598,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2519,8 +2636,6 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) result = BitConverter.DoubleToUInt64Bits(floatingResult); WriteMemoryRegister(operandStart, result); - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; - if (floatingResult > floatingInitial) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Carry; @@ -2530,6 +2645,9 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -2538,6 +2656,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2624,6 +2743,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; + +#if EXTENSION_SET_SIGNED Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if ((result & SignBit) != 0) @@ -2634,6 +2755,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (result == 0) { @@ -2659,6 +2781,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; + +#if EXTENSION_SET_SIGNED Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if ((result & SignBit) != 0) @@ -2669,6 +2793,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2698,6 +2823,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; + +#if EXTENSION_SET_SIGNED Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if ((result & SignBit) != 0) @@ -2708,6 +2835,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2746,6 +2874,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) WriteMemoryRegister(operandStart, result); Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; + +#if EXTENSION_SET_SIGNED Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if ((result & SignBit) != 0) @@ -2756,6 +2886,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (result == 0) { @@ -2790,9 +2921,6 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_Low_FloatingPoint_Comparison, opcodeLow)); } floatingResult = floatingInitial - floatingMathend; - result = BitConverter.DoubleToUInt64Bits(floatingResult); - - Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; if (floatingInitial < floatingMathend) { @@ -2803,6 +2931,11 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Carry; } +#if EXTENSION_SET_SIGNED + result = BitConverter.DoubleToUInt64Bits(floatingResult); + + Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Overflow; + if ((result & SignBit) != 0) { Registers[(int)Register.rsf] |= (ulong)StatusFlags.Sign; @@ -2811,6 +2944,7 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) { Registers[(int)Register.rsf] &= ~(ulong)StatusFlags.Sign; } +#endif if (floatingResult == 0) { @@ -2825,6 +2959,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_FloatingPoint, opcodeHigh)); } break; +#endif +#if EXTENSION_SET_EXTENDED_BASE case 0x3: // Extended base set switch (opcodeHigh) { @@ -2894,6 +3030,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_Extended, opcodeHigh)); } break; +#endif +#if EXTENSION_SET_EXTERNAL_ASM case 0x4: // External Assembly Extension Set switch (opcodeHigh) { @@ -3177,6 +3315,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_External, opcodeHigh)); } break; +#endif +#if EXTENSION_SET_HEAP_ALLOCATE case 0x5: // Memory Allocation Extension Set switch (opcodeHigh) { @@ -3343,6 +3483,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_Allocation, opcodeHigh)); } break; +#endif +#if EXTENSION_SET_FILE_SYSTEM case 0x6: // File System Extension Set switch (opcodeHigh) { @@ -3614,6 +3756,8 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_FileSystem, opcodeHigh)); } break; +#endif +#if EXTENSION_SET_TERMINAL case 0x7: // Terminal Extension Set switch (opcodeHigh) { @@ -3758,9 +3902,11 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_High_Terminal, opcodeHigh)); } break; - default: +#endif + default: throw new InvalidOpcodeException(string.Format(Strings.Processor_Error_Opcode_Extension_Set, extensionSet)); } +#if EXTENSION_SET_HEAP_ALLOCATE ulong newSO = Registers[(int)Register.rso]; if (MapStack && newSO != oldSO) { @@ -3775,10 +3921,12 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) throw new StackSizeException(Strings.Processor_Error_Stack_Collide); } } +#endif } while (runUntilHalt && !halt); return halt; } +#if EXTENSION_SET_EXTERNAL_ASM private static Assembly? ExtLoadContext_Resolving(AssemblyLoadContext loadContext, AssemblyName assemblyName) { try @@ -3794,7 +3942,9 @@ is not (ulong)StatusFlags.Sign and not (ulong)StatusFlags.Overflow) return null; } } +#endif +#if EXTENSION_SET_HEAP_ALLOCATE /// /// Allocate a block of memory with a given size into the processor memory map. /// @@ -3906,6 +4056,7 @@ public bool FreeMemory(ulong address) } return false; } +#endif /// /// Read a word (16 bit, 2 byte, unsigned, integer) from the given memory offset. diff --git a/Program.Shared.cs b/Program.Shared.cs index 514124b..3d6b894 100644 --- a/Program.Shared.cs +++ b/Program.Shared.cs @@ -53,16 +53,21 @@ public static Processor LoadExecutableToProcessor(string appPath, ulong memSize, { byte[] program; Processor processor; +#if V1_CALL_STACK_COMPAT if (useV1Format) { program = File.ReadAllBytes(appPath); processor = new Processor(memSize, entryPoint: 0, useV1CallStack: true, mapStack: mapStack, autoEcho: autoEcho); } else +#endif { AAPFile file = LoadAAPFile(appPath, ignoreNewerVersion); processor = new Processor(memSize, entryPoint: file.EntryPoint, - useV1CallStack: useV1CallStack || file.Features.HasFlag(AAPFeatures.V1CallStack), mapStack: mapStack, autoEcho: autoEcho); +#if V1_CALL_STACK_COMPAT + useV1CallStack: useV1CallStack || file.Features.HasFlag(AAPFeatures.V1CallStack), +#endif + mapStack: mapStack, autoEcho: autoEcho); program = file.Program; } LoadProgramIntoProcessor(processor, program); @@ -249,14 +254,18 @@ public static void ExecuteProcessor(Processor processor) { Console.WriteLine(Strings.CLI_Warning_Processor_Exit_File_Open); } +#if EXTENSION_SET_EXTERNAL_ASM if (processor.IsExternalOpen) { Console.WriteLine(Strings.CLI_Warning_Processor_Exit_External_Open); } +#endif +#if EXTENSION_SET_HEAP_ALLOCATE if (processor.AnyRegionsMapped) { Console.WriteLine(Strings.CLI_Warning_Processor_Exit_Region_Mapped, processor.MappedMemoryRanges.Count - 2); } +#endif Console.ResetColor(); } catch (Exception e) diff --git a/Program.cs b/Program.cs index 25c82a5..057cd4d 100644 --- a/Program.cs +++ b/Program.cs @@ -15,13 +15,16 @@ private static void Main(string[] args) if (args.Contains("--version", StringComparer.OrdinalIgnoreCase)) { Console.WriteLine(version?.ToString()); + Console.WriteLine(string.Join('|', Enum.GetValues() + .Where(v => v != 0 && ((v & (v - 1)) == 0)).Select(Enum.GetName).Where(n => n != "All").Distinct())); return; } if (!args.Contains("--no-header", StringComparer.OrdinalIgnoreCase)) { // Write to stderr to prevent header being included in redirected stdout streams - Console.Error.WriteLine($"AssEmbly {version?.Major}.{version?.Minor}.{version?.Build} {(Environment.Is64BitProcess ? "64-bit" : "32-bit")}" + - $" - CLR {Environment.Version}, {Environment.OSVersion} {(Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit")}"); + Console.Error.WriteLine($"AssEmbly {version?.Major}.{version?.Minor}.{version?.Build}-{(ulong)AAPFeatures.All:X}" + + $" {(Environment.Is64BitProcess ? "64-bit" : "32-bit")} - CLR {Environment.Version}, {Environment.OSVersion}" + + $" {(Environment.Is64BitOperatingSystem ? "64-bit" : "32-bit")}"); Console.Error.WriteLine(Strings.Generic_Copyright_Header); #if DEBUG Console.Error.WriteLine("(DEBUG BUILD)"); @@ -88,8 +91,10 @@ private static void AssembleSourceFile(string[] args) HashSet disabledErrors = new(); HashSet disabledWarnings = new(); HashSet disabledSuggestions = new(); +#if V1_CALL_STACK_COMPAT bool useV1Format = false; bool useV1Stack = false; +#endif bool enableObsoleteDirectives = false; bool enableVariableExpansion = true; bool enableEscapeSequences = true; @@ -145,6 +150,7 @@ private static void AssembleSourceFile(string[] args) { disabledSuggestions = AssemblerWarnings.SuggestionMessages.Keys.ToHashSet(); } +#if V1_CALL_STACK_COMPAT else if (a.Equals("--v1-format", StringComparison.OrdinalIgnoreCase)) { useV1Format = true; @@ -154,6 +160,7 @@ private static void AssembleSourceFile(string[] args) { useV1Stack = true; } +#endif else if (a.Equals("--allow-old-directives", StringComparison.OrdinalIgnoreCase)) { enableObsoleteDirectives = true; @@ -174,7 +181,13 @@ private static void AssembleSourceFile(string[] args) int totalSuggestions = 0; try { - Assembler assembler = new(useV1Format, useV1Stack, disabledErrors, disabledWarnings, disabledSuggestions); + Assembler assembler = new( +#if V1_CALL_STACK_COMPAT + useV1Format, useV1Stack, +#else + false, false, +#endif + disabledErrors, disabledWarnings, disabledSuggestions); if (macroExpansionLimit >= 0) { assembler.MacroExpansionLimit = macroExpansionLimit; @@ -266,21 +279,27 @@ private static void AssembleSourceFile(string[] args) string destination = args.Length >= 3 && !args[2].StartsWith('-') ? args[2] : filename + ".aap"; long programSize = 0; +#if V1_CALL_STACK_COMPAT if (useV1Format) { File.WriteAllBytes(destination, assemblyResult.Program); } else +#endif { AAPFeatures features = assemblyResult.UsedExtensions; +#if V1_CALL_STACK_COMPAT if (useV1Stack) { features |= AAPFeatures.V1CallStack; } +#endif +#if GZIP_COMPRESSION if (args.Contains("--compress", StringComparer.OrdinalIgnoreCase)) { features |= AAPFeatures.GZipCompressed; } +#endif AAPFile executable = new(version ?? new Version(), features, assemblyResult.EntryPoint, assemblyResult.Program); byte[] bytes = executable.GetBytes(); File.WriteAllBytes(destination, executable.GetBytes()); @@ -305,16 +324,29 @@ private static void AssembleSourceFile(string[] args) if (args.Contains("--compress", StringComparer.OrdinalIgnoreCase)) { Console.WriteLine(Strings.CLI_Assemble_Result_Success_Compressed, assemblyResult.Program.LongLength, Path.GetFullPath(destination), - useV1Format ? assemblyResult.Program.LongLength : programSize, - (double)(useV1Format ? assemblyResult.Program.LongLength : programSize) / assemblyResult.Program.LongLength, - useV1Format ? assemblyResult.Program.LongLength : programSize + AAPFile.HeaderSize, +#if V1_CALL_STACK_COMPAT + useV1Format ? assemblyResult.Program.LongLength : +#endif + programSize, + (double)( +#if V1_CALL_STACK_COMPAT + useV1Format ? assemblyResult.Program.LongLength : +#endif + programSize) / assemblyResult.Program.LongLength, +#if V1_CALL_STACK_COMPAT + useV1Format ? assemblyResult.Program.LongLength : +#endif + programSize + AAPFile.HeaderSize, totalErrors, totalWarnings, totalSuggestions, assemblyResult.AssembledLines.Length, assemblyResult.AssembledFiles, assemblyStopwatch.Elapsed.TotalMilliseconds); } else { Console.WriteLine(Strings.CLI_Assemble_Result_Success, assemblyResult.Program.LongLength, Path.GetFullPath(destination), - useV1Format ? assemblyResult.Program.LongLength : assemblyResult.Program.LongLength + AAPFile.HeaderSize, +#if V1_CALL_STACK_COMPAT + useV1Format ? assemblyResult.Program.LongLength : +#endif + assemblyResult.Program.LongLength + AAPFile.HeaderSize, totalErrors, totalWarnings, totalSuggestions, assemblyResult.AssembledLines.Length, assemblyResult.AssembledFiles, assemblyStopwatch.Elapsed.TotalMilliseconds); } @@ -332,8 +364,12 @@ private static void ExecuteProgram(string[] args) ulong memSize = GetMemorySize(args); Processor processor = LoadExecutableToProcessor(appPath, memSize, +#if V1_CALL_STACK_COMPAT args.Contains("--v1-format", StringComparer.OrdinalIgnoreCase), args.Contains("--v1-call-stack", StringComparer.OrdinalIgnoreCase), +#else + false, false, +#endif args.Contains("--ignore-newer-version", StringComparer.OrdinalIgnoreCase), !args.Contains("--unmapped-stack", StringComparer.OrdinalIgnoreCase), args.Contains("--auto-echo", StringComparer.OrdinalIgnoreCase)); @@ -393,7 +429,9 @@ private static void AssembleAndExecute(string[] args) Processor processor = new( memSize, assemblyResult.EntryPoint, +#if V1_CALL_STACK_COMPAT useV1CallStack: args.Contains("--v1-call-stack", StringComparer.OrdinalIgnoreCase), +#endif mapStack: !args.Contains("--unmapped-stack", StringComparer.OrdinalIgnoreCase), autoEcho: args.Contains("--auto-echo", StringComparer.OrdinalIgnoreCase)); LoadProgramIntoProcessor(processor, assemblyResult.Program); @@ -412,8 +450,12 @@ private static void RunDebugger(string[] args) ulong memSize = GetMemorySize(args); Processor processor = LoadExecutableToProcessor(appPath, memSize, +#if V1_CALL_STACK_COMPAT args.Contains("--v1-format", StringComparer.OrdinalIgnoreCase), args.Contains("--v1-call-stack", StringComparer.OrdinalIgnoreCase), +#else + false, false, +#endif args.Contains("--ignore-newer-version", StringComparer.OrdinalIgnoreCase), !args.Contains("--unmapped-stack", StringComparer.OrdinalIgnoreCase), args.Contains("--auto-echo", StringComparer.OrdinalIgnoreCase)); @@ -438,11 +480,13 @@ private static void PerformDisassembly(string[] args) string disassembledProgram; byte[] program; +#if V1_CALL_STACK_COMPAT if (args.Contains("--v1-format", StringComparer.OrdinalIgnoreCase)) { program = File.ReadAllBytes(sourcePath); } else +#endif { AAPFile file = LoadAAPFile(sourcePath, args.Contains("--ignore-newer-version", StringComparer.OrdinalIgnoreCase)); @@ -477,7 +521,9 @@ private static void RunRepl(string[] args) { ulong memSize = GetMemorySize(args); Debugger debugger = new(true, memorySize: memSize, +#if V1_CALL_STACK_COMPAT useV1CallStack: args.Contains("--v1-call-stack", StringComparer.OrdinalIgnoreCase), +#endif mapStack: !args.Contains("--unmapped-stack", StringComparer.OrdinalIgnoreCase), autoEcho: args.Contains("--auto-echo", StringComparer.OrdinalIgnoreCase)); // Some program needs to be loaded or the processor won't run