// loader module // Version September 22, 2006 -- Visual Studio 2005 #include "Registers.h" #include "Mmemory.h" #include "Loader.h" #include "UseGlobals.h" // must include this to access global objects #include using namespace std; // Test harness by Catalin Patulea . // Please see http://vv.carleton.ca/~cat/code/a2th/. struct Verifications::art *Verifications::_p[0x1000] = {0}; static unsigned int wc = 0; void Org(unsigned int a) { wc = a; } void Data(unsigned int a, unsigned int v) { sIASreg.MAR = a; sIASreg.MBR = v; sIASmem.Mwrite(); } void Opcode(unsigned int v) { Data(wc++, v); } #define VerifyM(reg, value, mask) do { \ Registers mr = {0}, vr = {0}; \ mr.reg = (mask); \ vr.reg = (value); \ Verifications::Add(wc - 1, __LINE__, mr, vr); \ } while (0) #define Verify(reg, value) VerifyM(reg, value, 0xFFFF) void Loader::Load ( ) // load program and initialize PC { // Prepare some data in memory Data(0x000, 0xdead); Data(0x001, 0xbeef); Data(0x010, 0xbadc); Data(0xFFE, 0xffff); Data(0xFFF, 0xfffe); // Start code at 0x100 Org(sIASreg.PC = 0x100); // Test loading AC from a memory, including some edge cases Opcode(0x1000); Verify(MAR, 0x000); Verify(MBR, 0xdead); Verify(AC, 0xdead); Opcode(0x1001); Verify(MAR, 0x001); Verify(MBR, 0xbeef); Verify(AC, 0xbeef); Opcode(0x1FFF); Verify(MAR, 0xFFF); Verify(MBR, 0xfffe); Verify(AC, 0xfffe); // Test loading AC with immediate Opcode(0x2000); Verify(AC, 0x0000); Opcode(0x2100); Verify(AC, 0x0100); Opcode(0x2F00); Verify(AC, 0x0F00); Opcode(0x2FFF); Verify(AC, 0x0FFF); // Test storing AC into memory Opcode(0x2000); // Load AC with some value Opcode(0x4300); Verify(MAR, 0x300); Verify(MBR, 0x0000); // Store AC Opcode(0x1300); Verify(AC, 0x0000); // Read value back and verify Opcode(0x2111); Opcode(0x4BAD); Verify(MAR, 0xBAD); Verify(MBR, 0x0111); Opcode(0x1BAD); Verify(AC, 0x0111); Opcode(0x1010); // Load AC with value from memory (already tested) Opcode(0x4CCC); Verify(MAR, 0xCCC); Verify(MBR, 0xbadc); Opcode(0x1CCC); Verify(AC, 0xbadc); // Test adding to AC from memory Opcode(0x2000); // Clear AC Opcode(0x6001); Verify(AC, 0xbeef); Opcode(0x6FFF); Verify(AC, 0xbeef + 0xfffe); Opcode(0x6010); Verify(AC, 0xbeef + 0xfffe + 0xbadc); // Test incrementing AC Opcode(0x2000); Opcode(0x8000); Verify(AC, 0x0001); Opcode(0x8000); Verify(AC, 0x0002); Opcode(0x1FFE); Opcode(0x8000); Verify(AC, 0x0000); // Check rollover // Test XOR AC from memory Opcode(0x2000); Opcode(0xA000); Verify(AC, 0xdead); Opcode(0xA001); Verify(AC, 0xdead ^ 0xbeef); Opcode(0xAFFE); Verify(AC, 0xdead ^ 0xbeef ^ 0xffff); // Test shift AC left Opcode(0x2001); Opcode(0xB000); Verify(AC, 0x0001); Opcode(0xB006); Verify(AC, 0x0040); Opcode(0xB009); Verify(AC, 0x8000); Opcode(0xB001); Verify(AC, 0x0000); // Test shift completely out of AC // Test load AC with sign-extended immediate (tricky business!) Opcode(0xC000); Verify(AC, 0x0000); Opcode(0xC123); Verify(AC, 0x0123); Opcode(0xC800); Verify(AC, 0xF800); Opcode(0xCCCC); Verify(AC, 0xFCCC); Opcode(0xCFFF); Verify(AC, 0xFFFF); // Test jump Opcode(0xE080); Verify(PC, 0x080); Org(0x080); // Continue writing opcodes where the CPU is supposed to end up Opcode(0xEA00); Verify(PC, 0xA00); Org(0xA00); // Test PC rollover (Mem[0xFFF] contains 0xFxxx, i.e. HALT) Opcode(0xEFFF); Verify(PC, 0x000); }