Skip to content

Commit

Permalink
Added new SinglePrecision class
Browse files Browse the repository at this point in the history
Needed to organize SinglePrecision code in preparation for
DoublePrecision operations
  • Loading branch information
jnosek committed Jul 15, 2015
1 parent 3976b3e commit 1170927
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 55 deletions.
2 changes: 2 additions & 0 deletions AGC/AGC.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,13 @@
<!-- A reference to the entire .NET Framework is automatically included -->
</ItemGroup>
<ItemGroup>
<Compile Include="Base\DoublePrecision.cs" />
<Compile Include="Base\ExtraInstructionList.cs" />
<Compile Include="Base\FixedMemory.cs" />
<Compile Include="Base\FullRegister.cs" />
<Compile Include="Base\MemoryBankOffset.cs" />
<Compile Include="Base\OnesCompliment.cs" />
<Compile Include="Base\SinglePrecision.cs" />
<Compile Include="Instructions\BranchZeroOrMinusToFixed.cs" />
<Compile Include="Instructions\ClearAndAdd.cs" />
<Compile Include="Instructions\ClearAndSubtract.cs" />
Expand Down
11 changes: 11 additions & 0 deletions AGC/Base/DoublePrecision.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Apollo.Virtual.AGC.Base
{
public class DoublePrecision
{
}
}
10 changes: 8 additions & 2 deletions AGC/Base/ErasableMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ public ErasableMemory(ushort address, MemoryBank bank)

public void Write(ushort value)
{
Set(value.OverflowCorrect());
var v = new OnesCompliment(value);
v.OverflowCorrect();

Set(v);
}

public ushort Read()
{
return Get().SignExtend();
var v = new OnesCompliment(Get());
v.SignExtend();

return v;
}
}
}
5 changes: 4 additions & 1 deletion AGC/Base/FixedMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ public void Write(ushort value)

public ushort Read()
{
return Get().SignExtend();
var v = new OnesCompliment(Get());
v.SignExtend();

return v;
}
}
}
92 changes: 62 additions & 30 deletions AGC/Base/OnesCompliment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,64 @@

namespace Apollo.Virtual.AGC.Base
{
public static class OnesCompliment
public class OnesCompliment
{
public const ushort NegativeZero = 0xFFFF;
public const ushort PositiveOne = 0x0001;
public const ushort NegativeOne = 0xFFFE;

public ushort Value { get; protected set; }

public OnesCompliment(ushort v)
{
Value = v;
}

public OnesCompliment(int v)
{
Value = ConvertToOnesCompliment(v);
}

public bool IsNegativeZero {
get
{
return Value == NegativeZero;
}
}

public bool IsPositiveZero
{
get
{
return Value == 0;
}
}

public bool IsNegative
{
get
{
return (Value & 0x8000) > 0;
}
}

/// <summary>
/// Automatically return ushort value for OnesCompliment value
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public static implicit operator ushort(OnesCompliment a)
{
return a.Value;
}


/// <summary>
/// Mainly used for converting 2's compliment negative numbers into Ones Compliment values
/// </summary>
/// <param name="value">2's Compliment Value (normal .net value)</param>
/// <returns>Ones Compliment coded value</returns>
public static ushort ToOnesCompliment(this int value)
protected static ushort ConvertToOnesCompliment(int value)
{
// if this is negative,
// return the 14 lower bits of the 1's compliment of the positive value
Expand All @@ -31,62 +77,48 @@ public static ushort ToOnesCompliment(this int value)
return (ushort)value;
}

/// <summary>
///
/// </summary>
/// <param name="left"></param>
/// <param name="right"></param>
/// <returns></returns>
public static ushort Add(this ushort left, ushort right)
{
var sum = left + right;

// if we have overflow, most likely from subtracting negative numbers
if ((sum & 0x10000) > 0)
{
// we need to ones compliment correct the negative number by adding 1 and taking the lower 16 bits
// this process is called "end around carry"
sum = sum + 1;
sum = sum & 0xFFFF;
}

return (ushort)sum;
}

/// <summary>
/// Performs overflow correction on a 16bit value, converting it to a 15 bit value
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static ushort OverflowCorrect(this ushort value)
public void OverflowCorrect()
{
uint newValue = value;
uint newValue = Value;

// get lower 14 bits
uint lowerBits = newValue & 0x3FFF;

// move 16-th bit, into 15th position, isolate it, and set it in above value;
newValue = (newValue >> 1 & 0x4000) | lowerBits;

return (ushort)newValue;
Value = (ushort)newValue;
}

/// <summary>
/// Performs sign extending on a 15bit value, converting it to a 16 bit value
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static ushort SignExtend(this ushort value)
public void SignExtend()
{
uint newValue = value;
uint newValue = Value;

// take lower 15-bits
newValue = newValue & 0x7FFF;

// shift left 1 and take 16th bit, combine with lower 15 bits
newValue = ((newValue << 1) & 0x8000) | newValue;

return (ushort)newValue;
Value = (ushort)newValue;
}
}

public static class OnesComplimentHelpers
{
public static OnesCompliment ToOnesCompliment(this int v)
{
return new OnesCompliment(v);
}
}
}
52 changes: 52 additions & 0 deletions AGC/Base/SinglePrecision.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Apollo.Virtual.AGC.Base
{
public class SinglePrecision : OnesCompliment
{
public SinglePrecision(ushort v)
: base(v)
{
}

public SinglePrecision(int v)
: base(v)
{
}

/// <summary>
/// Single Precision Addition
/// </summary>
/// <param name="left">left operand</param>
/// <param name="right">right operand</param>
/// <returns></returns>
public static SinglePrecision operator +(SinglePrecision left, OnesCompliment right)
{
var sum = left.Value + right.Value;

// if we have overflow, most likely from subtracting negative numbers
if ((sum & 0x10000) > 0)
{
// we need to ones compliment correct the negative number by adding 1 and taking the lower 16 bits
// this process is called "end around carry"
sum = sum + 1;
sum = sum & 0xFFFF;
}

return new SinglePrecision(sum);
}

public static SinglePrecision operator +(SinglePrecision left, ushort right)
{
return left + new SinglePrecision(right);
}

public static SinglePrecision operator ~(SinglePrecision a)
{
return new SinglePrecision((ushort)~a.Value);
}
}
}
8 changes: 4 additions & 4 deletions AGC/Instructions/Augment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,17 @@ public ushort Code

public void Execute(ushort K)
{
var value = CPU.Memory[K];
var value = new SinglePrecision(CPU.Memory[K]);

// if negative
if((value & 0x8000) > 0)
if(value.IsNegative)
{
CPU.Memory[K] = value.Add(OnesCompliment.NegativeOne);
CPU.Memory[K] = value + OnesCompliment.NegativeOne;
}
// if positive
else
{
CPU.Memory[K] = value.Add(OnesCompliment.PositiveOne);
CPU.Memory[K] = value + OnesCompliment.PositiveOne;
}
}
}
Expand Down
13 changes: 6 additions & 7 deletions AGC/Instructions/CountCompareAndSkip.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@ public ushort Code
public void Execute(ushort K)
{
// retrieve value from memory
var value = CPU.Memory[K];
var value = new SinglePrecision(CPU.Memory[K]);

// 1) compute the Diminished ABSolute value found at K and set in A

// if negative, NOT 1's to get ABS
var isNegative = (value & 0x8000) > 0;
var abs = (ushort)(isNegative ? ~value : value);
var abs = value.IsNegative ? ~value : value;

if (abs > 1)
CPU.A.Write(abs.Add(OnesCompliment.NegativeOne));
CPU.A.Write(abs + OnesCompliment.NegativeOne);
else
CPU.A.Write(0);

Expand All @@ -44,17 +43,17 @@ public void Execute(ushort K)
// if greater than +0 we do nothing, continue to next instruction as usual

// if == +0 increment by 1
if (value == 0)
if (value.IsPositiveZero)
CPU.Z.Increment();
// if == -0 increment by 3
else if(value == OnesCompliment.NegativeZero)
else if(value.IsNegativeZero)
{
CPU.Z.Increment();
CPU.Z.Increment();
CPU.Z.Increment();
}
// if < 0 increment by 2
else if (isNegative)
else if (value.IsNegative)
{
CPU.Z.Increment();
CPU.Z.Increment();
Expand Down
10 changes: 1 addition & 9 deletions AGC/Registers/Accumulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,7 @@ public Accumulator(MemoryBank bank)

public void Add(ushort value)
{
uint sum = Get().Add(value);

// if we have overflow, most likely from subtracting negative numbers
if((sum & 0x10000) > 0)
{
// we need to Single Precision correct the negative number by adding 1 and taking the lower 16 bits
sum = sum + 1;
sum = sum & 0xFFFF;
}
var sum = new SinglePrecision(value) + Get();

Set(sum);
}
Expand Down
9 changes: 7 additions & 2 deletions AGC/Registers/CycleRightRegister.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ public CycleRightRegister(MemoryBank bank)

public ushort Read()
{
return Get().SignExtend();
var v = new OnesCompliment(Get());
v.SignExtend();
return v;
}

public void Write(ushort value)
{
// first overflow correct the value
value = value.OverflowCorrect();
var v = new OnesCompliment(value);
v.OverflowCorrect();

value = v;

// get bit position 1, and move it to position 15
var leastSignificateBit = (value & 0x1) << 14;
Expand Down

0 comments on commit 1170927

Please sign in to comment.