Reputation: 9203
I was looking at the addressing modes for the MOS 6502 instruction set from the here.
The description of indirect, Y-indexed
is a bit inconsistent with other sources.
It says
OPC ($LL),Y operand is effective address incremented by Y with carry; effective address is word at zeropage address
But other sources don't mention about the addition with carry bit. Like here.
What is the right way of calculating the effective address?
Upvotes: 3
Views: 3059
Reputation: 44046
When in doubt it's better to look at the official documentation.
There is a fascinating original datasheet from MOS here
also [1] that reads
INDIRECT INDEXED ADDRESSING - In indirect indexed addressing (referred to as
( Indirect) , Y
), the second byte of the instruction points to a memory location in page zero.
The contents of this memory location is added to the contents of theY
index register, the result being the low order eight bits of the effective address.
The carry from this addition is added to the contents of the next page zero memory location, the result being the high order eight bits of the effective address.
So there the second addition is performed with carrying.
You can see this as a 16-bit addition between the 16-bit word pointed by Immediate
(in little-endian) and the contents of the Y
register zero extended to 16 bits.
For example, if the memory and Y
are
All values in hex
Address 00 01 02 03 04 ...
Value 80 02 f3 00 03 ...
Y = 90
then (0), Y
is
low 8 bits: 80 + 90 = 10 (with carry = 1)
high 8 bits: 02 + 00 + 1 = 03
giving an effective address of 0310
. Similarly (3), Y
is
low 8 bits: 00 + 90 = 90 (with carry = 0)
high 8 bits: 03 + 00 + 0 = 03
that results in an effective address of value 0390
.
You can see that when considered as 16-bit quantities the word at 0 is 0280
and Y
is 0090
, their addition is 0310
as expected.
The long description just encodes these facts: a) the 16-bit word pointed by Indirect
is stored in little-endian b) Y
is zero-extended c) the addition is a 16-bit one.
In C, it should look like this
uint16_t effective_addr(uint8_t indirect)
{
//Take the INDIRECT immediate and make a pointer to a 16-bit LE word out of it
//In C int-to-ptr is implementation define, we assume an identity map here
uint16_t* page_zero_ptr = (uint16_t*)indirect;
//The Y register is 8-bit, we consider it a 16-bit one instead
//Assume y is of unsigned type
uint16_t y_zero_ext = y;
//Do a 16-bit addition, this is equivalent to two 8-bit additions with carry
return *page_zero_ptr + y;
}
Upvotes: 11