mirror of
https://github.com/livingcomputermuseum/ContrAlto.git
synced 2026-01-21 18:14:54 +00:00
Added (temporary) code to debug floating point issue with Dance,Starwars.
This commit is contained in:
parent
41b6a76b2a
commit
b6e43080f2
@ -126,15 +126,12 @@ namespace Contralto.CPU
|
||||
// Invoke the task switch, this will take effect after
|
||||
// the NEXT instruction, not this one.
|
||||
TaskSwitch();
|
||||
}
|
||||
else
|
||||
}
|
||||
else if (_nextTask != null)
|
||||
{
|
||||
// If we have a new task, switch to it now.
|
||||
if (_nextTask != null)
|
||||
{
|
||||
_currentTask = _nextTask;
|
||||
_nextTask = null;
|
||||
}
|
||||
// If we have a new task, switch to it now.
|
||||
_currentTask = _nextTask;
|
||||
_nextTask = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +169,7 @@ namespace Contralto.CPU
|
||||
//
|
||||
WakeupTask(CPU.TaskType.DiskSector);
|
||||
|
||||
Log.Write(Logging.LogComponent.CPU, "Silent Boot; microcode banks initialized to {0}", Conversion.ToOctal(_rmr));
|
||||
Log.Write(LogComponent.CPU, "Silent Boot; microcode banks initialized to {0}", Conversion.ToOctal(_rmr));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -159,22 +159,24 @@ namespace Contralto.CPU
|
||||
}
|
||||
break;
|
||||
|
||||
case ShifterOp.RotateLeft:
|
||||
// TODO: optimize, this is stupid
|
||||
_output = input;
|
||||
for (int i = 0; i < _count; i++)
|
||||
{
|
||||
int c = (_output & 0x8000) >> 15;
|
||||
_output = (ushort)((_output << 1) | c);
|
||||
}
|
||||
|
||||
case ShifterOp.RotateLeft:
|
||||
if (_dns)
|
||||
{
|
||||
//
|
||||
// "Swap the 8-bit halves of the 16-bit result. The carry is not affected."
|
||||
//
|
||||
_output = (ushort)(((input & 0xff00) >> 8) | ((input & 0x00ff) << 8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: optimize, this is stupid
|
||||
_output = input;
|
||||
for (int i = 0; i < _count; i++)
|
||||
{
|
||||
int c = (_output & 0x8000) >> 15;
|
||||
_output = (ushort)((_output << 1) | c);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ShifterOp.RotateRight:
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Contralto.Logging;
|
||||
using System;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
@ -50,7 +51,7 @@ namespace Contralto.CPU
|
||||
// "When an S register is being loaded from M, the processor bus receives an
|
||||
// undefined value rather than being set to zero."
|
||||
_loadS = true;
|
||||
return 0xffff; // TODO: technically this is an "undefined value.".
|
||||
return 0xffff; // Technically this is an "undefined value," we're defining it as -1.
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException(String.Format("Unhandled bus source {0}", bs));
|
||||
@ -125,7 +126,7 @@ namespace Contralto.CPU
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log.Write(Logging.LogType.Warning, Logging.LogComponent.EmulatorTask, "STARTF for non-Ethernet device (code {0})",
|
||||
Log.Write(Logging.LogType.Warning, Logging.LogComponent.EmulatorTask, "STARTF for non-Ethernet device (code {0})",
|
||||
Conversion.ToOctal(_busData));
|
||||
}
|
||||
}
|
||||
@ -198,8 +199,7 @@ namespace Contralto.CPU
|
||||
_cpu._ir = _busData;
|
||||
|
||||
// "IR<- also merges bus bits 0, 5, 6 and 7 into NEXT[6-9] which does a first level
|
||||
// instruction dispatch."
|
||||
// TODO: is this an AND or an OR operation? (how is the "merge" done?)
|
||||
// instruction dispatch."
|
||||
// Assuming for now this is an OR operation like everything else that modifies NEXT.
|
||||
_nextModifier = (ushort)(((_busData & 0x8000) >> 12) | ((_busData & 0x0700) >> 8));
|
||||
|
||||
@ -302,8 +302,7 @@ namespace Contralto.CPU
|
||||
break;
|
||||
|
||||
case EmulatorF2.BUSODD:
|
||||
// "...merges BUS[15] into NEXT[9]."
|
||||
// TODO: is this an AND or an OR?
|
||||
// "...merges BUS[15] into NEXT[9]."
|
||||
_nextModifier |= (ushort)(_busData & 0x1);
|
||||
break;
|
||||
|
||||
@ -450,7 +449,7 @@ namespace Contralto.CPU
|
||||
// particular, if IR[12] is true, CARRY will not change. DNS also addresses R from (3-IR[3 - 4]), causes a store
|
||||
// into R unless IR[12] is set, and sets the SKIP flip flop if appropriate(see section 3.1). The emulator
|
||||
// microcode increments PC by 1 at the beginning of the next emulated instruction if SKIP is set, using
|
||||
// BUS+SKIP(ALUF= 13B). IR_ clears SKIP."
|
||||
// BUS+SKIP(ALUF= 13B). IR<- clears SKIP."
|
||||
//
|
||||
// NB: _skip is in the encapsulating AltoCPU class to make it easier to reference since the ALU needs to know about it.
|
||||
private int _carry;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
|
||||
using Contralto.Memory;
|
||||
using Contralto.Logging;
|
||||
|
||||
namespace Contralto.CPU
|
||||
{
|
||||
@ -92,16 +93,12 @@ namespace Contralto.CPU
|
||||
}
|
||||
|
||||
public bool ExecuteNext()
|
||||
{
|
||||
// TODO: cache microinstructions (or pre-decode them) to save consing all these up every time.
|
||||
{
|
||||
MicroInstruction instruction = UCodeMemory.GetInstruction(_mpc, _taskType);
|
||||
|
||||
// Grab BLOCK bit so that other tasks / hardware can look at it
|
||||
_block = instruction.F1 == SpecialFunction1.Block;
|
||||
|
||||
//Console.WriteLine("R5:{0},R6:{1},IR:{2} - {3}:{4}", OctalHelpers.ToOctal(_cpu._r[5]), OctalHelpers.ToOctal(_cpu._r[6]), OctalHelpers.ToOctal(_cpu._ir), OctalHelpers.ToOctal(_mpc), UCodeDisassembler.DisassembleInstruction(instruction, _taskType));
|
||||
|
||||
|
||||
|
||||
return ExecuteInstruction(instruction);
|
||||
}
|
||||
|
||||
@ -452,7 +449,7 @@ namespace Contralto.CPU
|
||||
if (swMode)
|
||||
{
|
||||
UCodeMemory.SwitchMode((ushort)(instruction.NEXT | nextModifier), _taskType);
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1}", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier));
|
||||
Log.Write(Logging.LogComponent.Microcode, "SWMODE: uPC {0}, next uPC {1}", Conversion.ToOctal(_mpc), Conversion.ToOctal(instruction.NEXT | nextModifier));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Contralto.Logging;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Contralto.CPU
|
||||
@ -126,7 +127,7 @@ namespace Contralto.CPU
|
||||
/// <param name="nextAddress"></param>
|
||||
public static void SwitchMode(ushort nextAddress, TaskType task)
|
||||
{
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: Current Bank {0}", _microcodeBank[(int)task]);
|
||||
Log.Write(Logging.LogComponent.Microcode, "SWMODE: Current Bank {0}", _microcodeBank[(int)task]);
|
||||
|
||||
switch (Configuration.SystemType)
|
||||
{
|
||||
@ -197,7 +198,7 @@ namespace Contralto.CPU
|
||||
break;
|
||||
}
|
||||
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "SWMODE: New Bank {0} for Task {1}", _microcodeBank[(int)task], task);
|
||||
Log.Write(Logging.LogComponent.Microcode, "SWMODE: New Bank {0} for Task {1}", _microcodeBank[(int)task], task);
|
||||
}
|
||||
|
||||
public static ushort ReadRAM()
|
||||
@ -207,7 +208,7 @@ namespace Contralto.CPU
|
||||
throw new NotImplementedException("Read from microcode ROM not implemented.");
|
||||
}
|
||||
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "CRAM address for read: Bank {0}, RAM {1}, lowhalf {2} addr {3}",
|
||||
Log.Write(Logging.LogComponent.Microcode, "CRAM address for read: Bank {0}, RAM {1}, lowhalf {2} addr {3}",
|
||||
_ramBank,
|
||||
_ramSelect,
|
||||
_lowHalfsel,
|
||||
@ -219,7 +220,7 @@ namespace Contralto.CPU
|
||||
// (See table in section 8.3 of HWRef.)
|
||||
ushort halfWord = (ushort)(_lowHalfsel ? data : (data >> 16));
|
||||
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "CRAM data read: {0}-{1}",
|
||||
Log.Write(Logging.LogComponent.Microcode, "CRAM data read: {0}-{1}",
|
||||
_lowHalfsel ? "low" : "high",
|
||||
Conversion.ToOctal(halfWord));
|
||||
|
||||
@ -234,11 +235,11 @@ namespace Contralto.CPU
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "CRAM address for write: Bank {0}, addr {1}",
|
||||
Log.Write(Logging.LogComponent.Microcode, "CRAM address for write: Bank {0}, addr {1}",
|
||||
_ramBank,
|
||||
Conversion.ToOctal(_ramAddr));
|
||||
|
||||
Logging.Log.Write(Logging.LogComponent.Microcode, "CRAM write of low {0}, high {1}",
|
||||
Log.Write(Logging.LogComponent.Microcode, "CRAM write of low {0}, high {1}",
|
||||
Conversion.ToOctal(low),
|
||||
Conversion.ToOctal(high));
|
||||
|
||||
@ -337,8 +338,6 @@ namespace Contralto.CPU
|
||||
{
|
||||
UInt32 instructionWord = _uCodeRam[address];
|
||||
_decodeCache[2048 + address] = new MicroInstruction(instructionWord);
|
||||
|
||||
//Console.WriteLine(_decodeCache[2048 + address]);
|
||||
}
|
||||
|
||||
private static RomFile[] _uCodeRoms =
|
||||
|
||||
2
Contralto/ClassDiagram1.cd
Normal file
2
Contralto/ClassDiagram1.cd
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram />
|
||||
2
Contralto/ClassDiagram2.cd
Normal file
2
Contralto/ClassDiagram2.cd
Normal file
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ClassDiagram />
|
||||
@ -179,6 +179,8 @@
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ClassDiagram1.cd" />
|
||||
<None Include="ClassDiagram2.cd" />
|
||||
<None Include="Disassembly\altocode24.mu" />
|
||||
<None Include="App.config" />
|
||||
<None Include="Disassembly\altoIIcode3.mu">
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -95,6 +95,8 @@ namespace Contralto.Display
|
||||
|
||||
_vblankScanlineCount = 0;
|
||||
|
||||
_dataBuffer.Clear();
|
||||
|
||||
// Schedule wakeup for first scanline of vblank
|
||||
_verticalBlankScanlineWakeup.TimestampNsec = _verticalBlankScanlineDuration;
|
||||
_system.Scheduler.Schedule(_verticalBlankScanlineWakeup);
|
||||
@ -265,8 +267,7 @@ namespace Contralto.Display
|
||||
|
||||
public void LoadDDR(ushort word)
|
||||
{
|
||||
_dataBuffer.Enqueue(word);
|
||||
|
||||
_dataBuffer.Enqueue(word);
|
||||
|
||||
// Sanity check: data length should never exceed 16 words.
|
||||
// TODO: we're allowing up to 18 before we start discarding things.
|
||||
|
||||
@ -225,8 +225,7 @@ namespace Contralto.IO
|
||||
|
||||
/// <summary>
|
||||
/// Commits modified sector data back to the emulated disk.
|
||||
/// Intended to be called at the end of the sector / beginning of the next.
|
||||
/// TODO: we should modify this so that checksums are persisted, possibly...
|
||||
/// Intended to be called at the end of the sector / beginning of the next.
|
||||
/// </summary>
|
||||
private void CommitSector()
|
||||
{
|
||||
|
||||
@ -19,8 +19,7 @@ namespace Contralto.IO
|
||||
Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: this is messy; the read and write sides of KDATA are distinct hardware.
|
||||
/// <summary>
|
||||
/// According to docs, on a Write, eventually it appears on the Read side during an actual write to the disk
|
||||
/// but not right away.
|
||||
/// </summary>
|
||||
@ -341,7 +340,7 @@ namespace Contralto.IO
|
||||
if (_seclateEnable)
|
||||
{
|
||||
_seclate = true;
|
||||
_kStat |= SECLATE; // TODO: move to constant field!
|
||||
_kStat |= SECLATE;
|
||||
Log.Write(LogComponent.DiskSectorTask, "SECLATE for sector {0}.", _sector);
|
||||
}
|
||||
}
|
||||
@ -476,7 +475,7 @@ namespace Contralto.IO
|
||||
//
|
||||
// If the clock is enabled OR the WFFO bit is set (go ahead and run the bit clock)
|
||||
// and we weren't late reading this sector, then we will wake up the word task
|
||||
// and read in the data if transfers are not inhibited. TODO: this should only happen on reads.
|
||||
// and read in the data if transfers are not inhibited.
|
||||
//
|
||||
if (!_seclate && (_wffo || _diskBitCounterEnable))
|
||||
{
|
||||
@ -525,7 +524,7 @@ namespace Contralto.IO
|
||||
// If the WFFO bit is cleared (wait for the sync word to be read)
|
||||
// then we check the word for a "1" (the sync word) to enable
|
||||
// the clock. This occurs late in the cycle so that the NEXT word
|
||||
// (not the sync word) is actually read. TODO: this should only happen on reads.
|
||||
// (not the sync word) is actually read.
|
||||
//
|
||||
if (!IsWrite() && !_wffo && diskWord.Data == 1)
|
||||
{
|
||||
|
||||
@ -163,8 +163,15 @@ namespace Contralto.IO
|
||||
while (true)
|
||||
{
|
||||
byte[] data = _udpClient.Receive(ref groupEndPoint);
|
||||
|
||||
// TODO: sanitize data before handing it off.
|
||||
|
||||
//
|
||||
// Sanitize the data (at least make sure the length is valid):
|
||||
//
|
||||
if (data.Length < 4)
|
||||
{
|
||||
Log.Write(LogType.Verbose, LogComponent.HostNetworkInterface, "Invalid packet: Packet is fewer than 2 words long, dropping.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Drop our own UDP packets.
|
||||
if (!groupEndPoint.Address.Equals(_thisIPAddress))
|
||||
|
||||
@ -55,7 +55,7 @@ namespace Contralto.Logging
|
||||
static Log()
|
||||
{
|
||||
// TODO: make configurable
|
||||
_components = LogComponent.None; // LogComponent.EthernetPacket | LogComponent.HostEthernet | LogComponent.EthernetController; // LogComponent.DiskController | LogComponent.DiskSectorTask | LogComponent.Debug | LogComponent.CPU; // LogComponent.EthernetController; // | LogComponent.Microcode | LogComponent.Memory | LogComponent.CPU;
|
||||
_components = LogComponent.None; // LogComponent.HostNetworkInterface | LogComponent.EthernetPacket; // | LogComponent.HostEthernet | LogComponent.EthernetController; // LogComponent.DiskController | LogComponent.DiskSectorTask | LogComponent.Debug | LogComponent.CPU; // LogComponent.EthernetController; // | LogComponent.Microcode | LogComponent.Memory | LogComponent.CPU;
|
||||
_type = LogType.Normal | LogType.Warning | LogType.Error | LogType.Verbose;
|
||||
|
||||
//_logStream = new StreamWriter("log.txt");
|
||||
|
||||
@ -296,7 +296,10 @@ namespace Contralto
|
||||
_frame++;
|
||||
|
||||
// Wait for the next frame
|
||||
_frameTimer.WaitForFrame();
|
||||
if (Configuration.ThrottleSpeed)
|
||||
{
|
||||
_frameTimer.WaitForFrame();
|
||||
}
|
||||
|
||||
if (Configuration.InterlaceDisplay)
|
||||
{
|
||||
|
||||
@ -13,6 +13,7 @@ using System.Threading;
|
||||
using System.Drawing.Imaging;
|
||||
using Contralto.IO;
|
||||
using Contralto.Display;
|
||||
using Contralto.Logging;
|
||||
|
||||
namespace Contralto
|
||||
{
|
||||
@ -805,6 +806,25 @@ namespace Contralto
|
||||
case ExecutionType.Normal:
|
||||
case ExecutionType.NextTask:
|
||||
case ExecutionType.NextNovaInstruction:
|
||||
|
||||
// For debugging floating point microcode:
|
||||
if (_system.CPU.CurrentTask.MPC == 0x10) // MPC is 20(octal) meaning a new Nova instruction.
|
||||
{
|
||||
if (_lastFPInstruction == 0)
|
||||
{
|
||||
// check for new floating instruction
|
||||
FloatDebugPre(_system.MemoryBus.DebugReadWord(TaskType.Emulator, _system.CPU.R[6]));
|
||||
}
|
||||
else
|
||||
{
|
||||
// last instruction was a floating point instruction, check the result
|
||||
FloatDebugPost();
|
||||
|
||||
// And see if this new one is also a floating point instruction...
|
||||
FloatDebugPre(_system.MemoryBus.DebugReadWord(TaskType.Emulator, _system.CPU.R[6]));
|
||||
}
|
||||
}
|
||||
|
||||
// See if we need to stop here
|
||||
if (_execAbort || // The Stop button was hit
|
||||
_microcodeBreakpointEnabled[(int)UCodeMemory.GetBank(_system.CPU.CurrentTask.TaskType),_system.CPU.CurrentTask.MPC] || // A microcode breakpoint was hit
|
||||
@ -835,7 +855,371 @@ namespace Contralto
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// vars for float debug
|
||||
ushort _lastFPInstruction;
|
||||
ushort _ac0;
|
||||
ushort _ac1;
|
||||
ushort _ac2;
|
||||
ushort _ac3;
|
||||
ushort _fpRegAddr;
|
||||
ushort _fpRegCount;
|
||||
|
||||
/// <summary>
|
||||
/// Temporary, for debugging floating point ucode issues
|
||||
/// </summary>
|
||||
/// <param name="instruction"></param>
|
||||
private void FloatDebugPre(ushort instruction)
|
||||
{
|
||||
_lastFPInstruction = 0;
|
||||
// Float instructions are from 70001-70022 octal
|
||||
if (instruction >= 0x7000 && instruction <= 0x7012)
|
||||
{
|
||||
// Save instruction
|
||||
_lastFPInstruction = instruction;
|
||||
|
||||
// Save ACs
|
||||
_ac0 = _system.CPU.R[3];
|
||||
_ac1 = _system.CPU.R[2];
|
||||
_ac2 = _system.CPU.R[1];
|
||||
_ac3 = _system.CPU.R[0];
|
||||
|
||||
Console.Write("FP: ");
|
||||
switch (instruction)
|
||||
{
|
||||
case 0x7000:
|
||||
Console.WriteLine("FPSetup");
|
||||
|
||||
_fpRegAddr = _system.CPU.R[3];
|
||||
_fpRegCount = _system.MemoryBus.DebugReadWord(TaskType.Emulator, _fpRegAddr);
|
||||
|
||||
Console.WriteLine(" FP register address {0}, count {1}", Conversion.ToOctal(_fpRegAddr), _fpRegCount);
|
||||
|
||||
break;
|
||||
|
||||
case 0x7001:
|
||||
Console.WriteLine("FML {0},{1} ({2},{3})", _ac0, _ac1, GetFloat(_ac0), GetFloat(_ac1));
|
||||
break;
|
||||
|
||||
case 0x7002:
|
||||
Console.WriteLine("FDV {0},{1} ({2},{3})", _ac0, _ac1, GetFloat(_ac0), GetFloat(_ac1));
|
||||
break;
|
||||
|
||||
case 0x7003:
|
||||
Console.WriteLine("FAD {0},{1} ({2},{3})", _ac0, _ac1, GetFloat(_ac0), GetFloat(_ac1));
|
||||
break;
|
||||
|
||||
case 0x7004:
|
||||
Console.WriteLine("FSB {0},{1} ({2},{3})", _ac0, _ac1, GetFloat(_ac0), GetFloat(_ac1));
|
||||
break;
|
||||
|
||||
case 0x7005:
|
||||
Console.WriteLine("FLD {0},{1} (src {2})", _ac0, _ac1, GetFloat(_ac1));
|
||||
break;
|
||||
|
||||
case 0x7006:
|
||||
Console.WriteLine("FLDV {0},{1} (src {2})", _ac0, _ac1, GetFloatFromInternalFormat(_ac1));
|
||||
break;
|
||||
|
||||
case 0x7007:
|
||||
Console.WriteLine("FSTV {0},{1} (src {2})", _ac0, _ac1, GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7008:
|
||||
Console.WriteLine("FLDI {0},{1}", _ac0, Conversion.ToOctal(_ac1));
|
||||
break;
|
||||
|
||||
case 0x7009:
|
||||
Console.WriteLine("FTR {0} ({1})", _ac0, GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x700a:
|
||||
Console.WriteLine("FNEG {0} ({1})", _ac0, GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x700b:
|
||||
Console.WriteLine("FSN {0} ({1})", _ac0, GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x700c:
|
||||
Console.WriteLine("FCM {0} ({1})", _ac0, GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x700d:
|
||||
Console.WriteLine("FST");
|
||||
break;
|
||||
|
||||
case 0x700e:
|
||||
Console.WriteLine("FLDDP");
|
||||
break;
|
||||
|
||||
case 0x700f:
|
||||
Console.WriteLine("FSTDP");
|
||||
break;
|
||||
|
||||
case 0x7010:
|
||||
Console.WriteLine("DPAD");
|
||||
break;
|
||||
|
||||
case 0x7011:
|
||||
Console.WriteLine("DPSB");
|
||||
break;
|
||||
|
||||
case 0x7012:
|
||||
Console.WriteLine("FEXP {0},{1} ({2})", _ac0, _ac1, GetFloat(_ac0));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
Console.WriteLine(" AC0={0} AC1={1} AC2={2} AC3={3}",
|
||||
Conversion.ToOctal(_ac0),
|
||||
Conversion.ToOctal(_ac1),
|
||||
Conversion.ToOctal(_ac2),
|
||||
Conversion.ToOctal(_ac3)); */
|
||||
}
|
||||
}
|
||||
|
||||
private void FloatDebugPost()
|
||||
{
|
||||
|
||||
Console.Write("Post: ");
|
||||
switch (_lastFPInstruction)
|
||||
{
|
||||
case 0x7000:
|
||||
Console.WriteLine("FPSetup done.");
|
||||
break;
|
||||
|
||||
case 0x7001:
|
||||
Console.WriteLine("Result {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7002:
|
||||
Console.WriteLine("Result {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7003:
|
||||
Console.WriteLine("Result {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7004:
|
||||
Console.WriteLine("Result {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7005:
|
||||
Console.WriteLine("Loaded {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7006:
|
||||
Console.WriteLine("Loaded {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7007:
|
||||
Console.WriteLine("FSTV done.");
|
||||
break;
|
||||
|
||||
case 0x7008:
|
||||
Console.WriteLine("Loaded {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x7009:
|
||||
Console.WriteLine("Result {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x700a:
|
||||
Console.WriteLine("Result {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
case 0x700b:
|
||||
Console.WriteLine("Result {0}", _ac3);
|
||||
break;
|
||||
|
||||
case 0x700c:
|
||||
Console.WriteLine("Result {0}", _ac3);
|
||||
break;
|
||||
|
||||
case 0x700d:
|
||||
Console.WriteLine("FST done.");
|
||||
break;
|
||||
|
||||
case 0x700e:
|
||||
Console.WriteLine("FLDDP done.");
|
||||
break;
|
||||
|
||||
case 0x700f:
|
||||
Console.WriteLine("FSTDP done.");
|
||||
break;
|
||||
|
||||
case 0x7010:
|
||||
Console.WriteLine("DPAD done.");
|
||||
break;
|
||||
|
||||
case 0x7011:
|
||||
Console.WriteLine("DPSB done.");
|
||||
break;
|
||||
|
||||
case 0x7012:
|
||||
Console.WriteLine("Result {0}", GetFloat(_ac0));
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidOperationException("Unexpected op for post.");
|
||||
}
|
||||
|
||||
_lastFPInstruction = 0;
|
||||
}
|
||||
|
||||
private double GetFloat(ushort arg)
|
||||
{
|
||||
// If arg is less than the number of registers, it's assumed
|
||||
// to be a register; otherwise an address
|
||||
if (arg < _fpRegCount)
|
||||
{
|
||||
return GetFloatFromUcode(arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetFloatFromPackedFormat(arg);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a float from memory in "packed" format
|
||||
/// </summary>
|
||||
/// <param name="addr"></param>
|
||||
/// <returns></returns>
|
||||
private double GetFloatFromPackedFormat(ushort addr)
|
||||
{
|
||||
//
|
||||
// Packed format is only two words:
|
||||
// structure FP: [
|
||||
// sign bit 1 //1 if negative.
|
||||
// expon bit 8 //excess 128 format (complemented if number <0)
|
||||
// mantissa1 bit 7 //High order 7 bits of mantissa
|
||||
// mantissa2 bit 16 //Low order 16 bits of mantissa
|
||||
// ]
|
||||
//
|
||||
uint packedWord =
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, addr) << 16) |
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 1)));
|
||||
|
||||
double sign = (packedWord & 0x80000000) != 0 ? -1.0 : 1.0;
|
||||
uint exponent = (packedWord & 0x7f800000) >> 23;
|
||||
uint mantissa = (packedWord & 0x007fffff);
|
||||
|
||||
double val = 0.0;
|
||||
for (int i = 0; i < 23; i++)
|
||||
{
|
||||
double bit = (mantissa & (0x00400000 >> i)) != 0 ? 1.0 : 0.0;
|
||||
|
||||
val += (bit * (1.0 / Math.Pow(2.0, (double)i)));
|
||||
}
|
||||
|
||||
double adjustedExponent = exponent - 128.0;
|
||||
|
||||
val = sign * (val) * Math.Pow(2.0, adjustedExponent);
|
||||
|
||||
Console.WriteLine("packed: {0}", val);
|
||||
|
||||
return val;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the float value for register, from alto code
|
||||
/// </summary>
|
||||
/// <param name="reg"></param>
|
||||
/// <returns></returns>
|
||||
private double GetFloatFromInternalFormat(ushort addr)
|
||||
{
|
||||
|
||||
// Internal format is 4 words long:
|
||||
// Word 0: sign
|
||||
// Word 1: exponent
|
||||
// Word 2-3: mantissa
|
||||
//
|
||||
|
||||
double sign = (_system.MemoryBus.DebugReadWord(TaskType.Emulator, addr)) != 0 ? -1.0 : 1.0;
|
||||
int exponent = (int)(short)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 1)));
|
||||
uint mantissa =
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 2)) << 16) |
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(addr + 3)));
|
||||
|
||||
double val = 0.0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
double bit = (mantissa & (0x80000000 >> i)) != 0 ? 1.0 : 0.0;
|
||||
|
||||
val += (bit * (1.0 / Math.Pow(2.0, (double)i)));
|
||||
}
|
||||
|
||||
val = sign * (val) * Math.Pow(2.0, exponent - 1);
|
||||
|
||||
if (double.IsInfinity(val) || double.IsNaN(val))
|
||||
{
|
||||
Console.WriteLine(" ERROR: sign {0} exp {1} mantissa {2:x} value {3}",
|
||||
sign,
|
||||
exponent,
|
||||
mantissa,
|
||||
val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the float value for register, from ucode store
|
||||
/// </summary>
|
||||
/// <param name="reg"></param>
|
||||
/// <returns></returns>
|
||||
private double GetFloatFromUcode(ushort reg)
|
||||
{
|
||||
|
||||
// Internal format is 4 words long:
|
||||
// Word 0: sign
|
||||
// Word 1: exponent
|
||||
// Word 2-3: mantissa
|
||||
//
|
||||
// In current ucode, each word is staggered across the FP buffer space rather than being in linear order to prevent having to do multiplies.
|
||||
// For FP register N of M total registers starting at offset O:
|
||||
// Word 0 is at O + N + 1
|
||||
// Word 1 is at O + N + M + 1
|
||||
// Word 2 is at O + N + 2*M + 1
|
||||
// Word 3 is at O + N + 3*M + 1
|
||||
ushort oreg = reg;
|
||||
|
||||
|
||||
reg += _fpRegAddr;
|
||||
reg++;
|
||||
|
||||
//Console.WriteLine("reg base {0}, num {1} addr {2}", _fpRegAddr, oreg, Conversion.ToOctal(reg));
|
||||
|
||||
// reg is now an address; read things in...
|
||||
double sign = (_system.MemoryBus.DebugReadWord(TaskType.Emulator, reg)) != 0 ? -1.0 : 1.0;
|
||||
int exponent = (int)(short)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(reg + _fpRegCount)));
|
||||
uint mantissa =
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(reg + 2 * _fpRegCount)) << 16) |
|
||||
(uint)(_system.MemoryBus.DebugReadWord(TaskType.Emulator, (ushort)(reg + 3 * _fpRegCount)));
|
||||
|
||||
double val = 0.0;
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
double bit = (mantissa & (0x80000000 >> i)) != 0 ? 1.0 : 0.0;
|
||||
|
||||
val += (bit * (1.0 / Math.Pow(2.0, (double)i)));
|
||||
}
|
||||
|
||||
val = sign * (val) * Math.Pow(2.0, exponent - 1);
|
||||
|
||||
if (double.IsInfinity(val) || double.IsNaN(val))
|
||||
{
|
||||
Console.WriteLine(" ERROR: sign {0} exp {1} mantissa {2:x} value {3}",
|
||||
sign,
|
||||
exponent,
|
||||
mantissa,
|
||||
val);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
private void SetExecutionState(ExecutionState state)
|
||||
{
|
||||
@ -961,7 +1345,7 @@ namespace Contralto
|
||||
private void HackButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
Logging.Log.LogComponents |= Logging.LogComponent.TaskSwitch;
|
||||
Logging.Log.Write(Logging.LogComponent.Debug, "***** HACK HIT ******");
|
||||
Log.Write(Logging.LogComponent.Debug, "***** HACK HIT ******");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user