6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Sep 28, 2024 1:33 am

All times are UTC




Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Sun Jun 11, 2017 10:39 pm 
Offline
User avatar

Joined: Wed Mar 01, 2017 8:54 pm
Posts: 660
Location: North-Germany
zp, zp+1 would contain a pointer to the base of a list of pointers again 2 bytes each, that's why 2X, to address up to 256 of them. This indexed pointer is taken and postindexed by Y.

edit(1):
I was thinking of 8 bit index registers and 8 bit data bus width. Just plain 6502 :)


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 12, 2017 12:25 am 
Offline
User avatar

Joined: Mon Apr 23, 2012 12:28 am
Posts: 760
Location: Huntsville, AL
GaBuZoMeu:
MichaelM wrote:
In relation to this new addressing mode, would ((zp),X),Y be okay if X and Y are 16 bits, or BuGaGa bits, wide.
I certainly agree the factor of two is warranted if X and Y are both 8-bit index registers. When X or Y is a 16-bit register, then the addressing mode is better thought of as base + offset. The base is in the register and the offset is in the instruction. I assume from the answer above, if X is a 16-bit register, the factor of 2 is not required on the inner post-indexed (by X) indirect read.

I realized that extending the X and Y registers to 16-bits changed the effect of the index registers in the indexed addressing modes of the 6502/65C02. For example, zp,X, (zp,X), abs,X, and (abs,X) could be used to support base pointer relative addressing of variables on the stack. If X is assigned the value of the stack pointer immediately after entry into a subroutine, it functions as a base pointer providing easy access to the parameters passed to the subroutine with positive offsets, and the local variables of the subroutine with negative offsets. These offsets are fixed and easily calculated by a compiler or assembler. With a 16-bit index register, the pre-indexed (by X) addressing modes of the 6502/65C02 become quite powerful, and I expect, require significantly less programming effort to manage split stack push and pop operations as discussed by 6502/65C02 FORTH programmers to improve performance. Even the post-indexed by Y addressing modes are affected positively by extending the Y register to 16 bits.

For stack pointer relative addressing, the X and S registers (S is also extended to 16-bits) are swapped using a prefix instruction in my extended 65C02-compatible core. S could be copied to X using TSX, and Y used as the base pointer, but given the dynamic nature of expression evaluation stacks for which built-in stack pointer relative addressing is almost required, I felt that it would be more natural to swap the S and X registers using a prefix instruction. (Note: Without the siz prefix instruction TSX only transfers the least significant 8-bits of S to X. For transparent compatibility with 6502/65C02 code, an 8-bit transfer from X to S using TXS automatically sets the system stack to page 1 where it normally resides. When the system stack is in page 1, the stack size is automatically limited to 256 bytes. If S is set outside of page 1 (or page 0) using a 16-bit transfer, the stack is limited only by available memory.)

The 6502 overcomes the limitations of its 8-bit index registers by providing more powerful addressing modes. The 16-bit index register of the 6800 processor provides that processor some advantage over the 6502/65C02, but having a limited number of addressing modes limits the utility of its 16-bit index register. The 6809 with two 16-bit index registers is a tough competitor. As Brad Rodriguez, Camel FORTH developer, demonstrated in his "Starting FORTH" series of articles. the 16-bit index registers of the 6809 enable a very efficient FORTH VM.

_________________
Michael A.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 12, 2017 12:49 am 
Offline
User avatar

Joined: Wed Mar 01, 2017 8:54 pm
Posts: 660
Location: North-Germany
I merely took the TO's question and add this double indirect post indexed variant. Others (like stack relative) were already mentioned.

I did not consider Forth nor 16 bit index registers at all.

16 bit index registers would impact the addressing modes a lot if 16 bit would cover the full address range - otherwise not.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 22, 2017 10:12 am 
Offline

Joined: Wed Oct 06, 2010 9:05 am
Posts: 95
Location: Palma, Spain
It struck me that an addressing mode that I'd've loved to have on the 6502 is "from stack". Quite often you have a value on the stack, and perhaps you want to add it to something. Currently you have to make sure that the 'something' is in memory so you can write:
Code:
PLA
ADC something

But how much nicer it would be if you already had that 'something' in the accumulator, and you could just write:
Code:
ADC S  ; pull data to add from stack

I guess it could have been a 4 cycle addressing mode, just like pull. The ALU operation at the end would be performed at the same time as the next opcode fetch.


Top
 Profile  
Reply with quote  
PostPosted: Thu Jun 22, 2017 9:24 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8520
Location: Southern California
RichTW wrote:
It struck me that an addressing mode that I'd've loved to have on the 6502 is "from stack". Quite often you have a value on the stack, and perhaps you want to add it to something. Currently you have to make sure that the 'something' is in memory so you can write:
Code:
PLA
ADC something

But how much nicer it would be if you already had that 'something' in the accumulator, and you could just write:
Code:
ADC S  ; pull data to add from stack

I guess it could have been a 4 cycle addressing mode, just like pull. The ALU operation at the end would be performed at the same time as the next opcode fetch.

The 65816 has stack-relative addressing modes which do exactly that. It can be done on the '02 as well, although with some limitations. The way to do it is that at the beginning of the section of code, you do a TSX, then use indexed addressing like ADC 101,X. You don't have to stop at just the byte at the top of the stack. You can operate on other ones in the stack, without pulling off the later-added bytes in order to get to what you want to access. Just increase the base number; for example,
Code:
        TSX
        CLC
        LDA  101,X
        ADC  103,X
        STA  103,X
        LDA  102,X
        ADC  104,X
        STA  104,X

The subroutine below multiplies two unsigned 16-bit numbers and produces a 32-bit result, without using any variables, only the page-1 hardware stack. It takes Bruce Clark's improvement on my commented bug fix on the UM* multiplication in fig-Forth, and it modifies it for I/O on the hardware stack. The structures are per my structure-macro article and source code linked there. They assemble exactly the same thing you would by hand, but make the conditions and branches in the source code clearer.
Code:
UM_STAR: LDA #0                 ; Unsigned, mixed-precision (16-bit by 16-bit input, 32-bit output)
         PHA                    ; multiply.  Add a variable byte to the stack, initializing it as 0.
         TSX                    ; Now 101,X holds that new variable, 102,X and 103,X hold the return
         LSR $107,X             ; address, and 104,X to 107,X holds the inputs and later the outputs.
         ROR $106,X
         FOR_Y  16, DOWN_TO, 0  ; Loop 16x.  The DEY, BNE in NEXT_Y below will drop through on 0.
             IF_CARRY_SET
                 CLC
                 PHA            ; Note that the PHA (and PLA below) doesn't affect the indexing.
                    LDA $101,X
                    ADC $104,X
                    STA $101,X
                 PLA
                 ADC $105,X
             END_IF
             ROR
             ROR $101,X
             ROR $107,X
             ROR $106,X
         NEXT_Y
         STA $105,X
         PLA                    ; Retrieve the variable byte we added at the top, cleaning up the stack.
         STA $104,X             ; Again note that the PLA changed S but not X, so the 104 is still 104.
         RTS
 ;------------------

If you want to preserve X, you can do the usual PHX, PLX.

This and lots more about stacks (plural, not just the page-1 hardware stack) is in my 6502 stacks treatise, at http://wilsonminesco.com/stacks/ .

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 26, 2017 3:50 pm 
Offline
User avatar

Joined: Tue Oct 25, 2016 8:56 pm
Posts: 362
Indeed, quite right Garth, though it would be nice to be able to do it without having to sacrifice X in the process - we've only got three registers to start with!

Just from my own programming of late, I find it quite irritating that the STX and STY instructions are so limited in addressing modes - Absolute, Zero Page and ZP,X. Of those three the only one that isn't fixed at compile time is ZP,X and it still restricts you to ZP only.

This is particularly strange given that the matching LDX and LDY instructions have a,y and a,x respectively which make it very easy to use them for virtual stack manipulation loads, but the corresponding store has to go through A. Even STZ, which isn't actually all that useful, has a,x mode!

Actual 65C02 code:
Code:
PushY:
    PHX
    PHA
    LDX     BIOS_SwsSP
    TYA
    STA     SWSTACK_BASE, X
    INX
    STX     BIOS_SwsSP
    PLA
    PLX
    RTS


Simplification if STY a,y existed:
Code:
PushY:
    PHX
    LDX     BIOS_SwsSP
    STY     SWSTACK_BASE, X
    INX
    STX     BIOS_SwsSP
    PLX
    RTS


Three instructions shorter, doesn't disturb A at all and, in my opinion, easier to understand what's going on. idk it just seems like an obvious oversight, and its not as though the 65C02 is lacking in spare opcodes.

_________________
Want to design a PCB for your project? I strongly recommend KiCad. Its free, its multiplatform, and its easy to learn!
Also, I maintain KiCad libraries of Retro Computing and Arduino components you might find useful.


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 26, 2017 11:05 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8520
Location: Southern California
Yes, I've often thought it would be nice to have a second X register (or a second hardware stack with its automatically incrementing and decrementing pointer, or [...], kind of like playing chess and wishing your pieces could move in directions they're not allowed to). Again though, the '816 largely takes care of that with its stack-relative addressing modes.

As mentioned earlier, Forth uses a data stack in ZP and uses X as its pointer. In my '02 ITC Forth, I very seldom have to save and restore X. It's almost exclusively for doing the looping controls. In my '816 Forth, the only thing I save X for is to synthesize the non-existent LDA (X),Y instruction for the ROLL and PICK instructions. (I have not searched all my INCLude files to see if there's any other I'm forgetting.) The things that use X so much in assembly language tend to use the data stack in Forth, which is one reason why the sometimes-ridiculed (ZP,X) addressing mode is valuable. It's like you're giving X a different job, rather than an additional job. I have carried this over into assembly language a little bit, and will probably do it a lot more in the future.

When I'm beating my head against a wall trying for force a certain solution, I usually find that it means I'm looking for the wrong solution, or need to back up and take a different approach to solve the problem or see if maybe I'm misunderstanding the problem itself. I've never needed to push Y onto a virtual stack. Would I, if I had to solve the same problems you were when you came to that? Maybe. I don't know. BDD did say above, "However, I can't recall any time recently when I wished I had STX <addr>,Y and STY <addr>,X available to me."

I like Ed's observation: "With 6502, I suspect more than one beginner has wondered why they can't do arithmetic or logic operations on X or Y, or struggled to remember which addressing modes use which of the two. And then the intermediate 6502 programmer will be loading and saving X and Y while the expert always seems to have the right values already in place."

BTW, I do use STZ a lot, probably mostly for clearing flag variables.

There's lots of interesting discussion here. Thanks.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 22 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: No registered users and 15 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: