Now that we have a value loaded into our IX Register, we can start using Indexed Addressing.
Indexed addressing works quite a bit differently than the other addressing modes we have used: such as Extended Addressing and Register Addressing. With Indexed Addressings, we take a base address and add a displacement to it and then use that value as our address into memory.
This displacement takes the form of a single Byte in twos complement format, which allows a range of +127 to -128.
Indexed Addressing is provided to enable program code to easily load data from a table.
Naturally, the first thing I did was create a test to implement the LD (IX + d), n instruction.
[TestMethod]
public void LoadConstantIntoIXdAddressValue()
{
var memory = new ListOfActionsMemory();
var cpu = new CPU(memory);
var loworderIXAddress = new ZByte(Bit.One, Bit.Zero,
Bit.Zero, Bit.One, Bit.One, Bit.Zero, Bit.One, Bit.Zero);
var highorderIXAddress = new ZByte(Bit.Zero, Bit.Zero,
Bit.One, Bit.Zero, Bit.Zero, Bit.Zero, Bit.Zero, Bit.One);
var valueByte = new ZByte(Bit.Zero, Bit.One, Bit.Zero,
Bit.One, Bit.One, Bit.Zero, Bit.One, Bit.Zero);
var displacementByte = new ZByte(Bit.Zero, Bit.Zero,
Bit.Zero, Bit.Zero, Bit.Zero, Bit.One, Bit.Zero, Bit.One);
var resultLowOrderAddress = new ZByte(Bit.One,
Bit.Zero, Bit.Zero, Bit.One, Bit.One, Bit.One, Bit.One, Bit.One);
var resultAddress =
new SixteenBitAddress(highorderIXAddress, resultLowOrderAddress);
cpu.PerformInstruction(LoadCommand.NNintoIX_First,
LoadCommand.NNintoIX_Second, loworderIXAddress, highorderIXAddress);
cpu.PerformInstruction(LoadCommand.ConstantIntoIXd_first,
LoadCommand.ConstantIntoIXd_second, displacementByte, valueByte);
Assert.AreEqual(resultAddress, memory.Saved[0].Item1);
Assert.AreEqual(valueByte, memory.Saved[0].Item2);
}
This test takes a value and stores it at the relevant location in memory.
This by itself was fairly straightforward and easy but then I decided to test a negative displacement.
At this point, each of my ZBytes are stored as a byte internally. A byte is unsigned.
My SixteenBitAddress
class is a UInt16
internally. This is also unsigned.
Luckily all of my values are actually defined by a series of Bits rather than as a value so converting a byte to an sbyte
(a signed byte) gives me the value I want (the range +127 to -128). However, UInt16
does not allow sbytes
to be added to them as adding a negative value could make the UInt16
negative (which by definition it can't be).
After a bit of research, I found out that .NET guarantees that integer types of a given bit size maintain their bit ordering when converted to different types. Which means that a UInt16
can be converted to an Int16
with no issues.
So I am now left with the method people to add a signed byte to a memory address.
public void AddSignedByte(ZByte value)
{
_internalInt = (UInt16) (((Int16) _internalInt) + ((sbyte)value));
}
What this is doing is taking advantage of the fact that an Int16
is a signed type and will therefore allow increments and decrements with other signed types. Then because the Int16
and UInt16
are the same bit size converting one to the other maintains the bit ordering.
So even if the value overflows under zero (assuming the displacement value is negative), then the memory read still won't try and read a negative address, but instead a very high one.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.