Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.sys.apple2.programmer > #2204 > unrolled thread
| Started by | Mark Lemmert <mark.lemmert@gmail.com> |
|---|---|
| First post | 2016-02-04 11:41 -0800 |
| Last post | 2016-02-04 21:20 -0800 |
| Articles | 5 — 4 participants |
Back to article view | Back to comp.sys.apple2.programmer
most efficient way to save/restore 6502 registers Mark Lemmert <mark.lemmert@gmail.com> - 2016-02-04 11:41 -0800
Re: most efficient way to save/restore 6502 registers Scott Hemphill <hemphill@hemphills.net> - 2016-02-04 15:31 -0500
Re: most efficient way to save/restore 6502 registers Mark Lemmert <mark.lemmert@gmail.com> - 2016-02-04 19:22 -0800
Re: most efficient way to save/restore 6502 registers Michael Barry <barrym95838@yahoo.com> - 2016-02-04 20:21 -0800
Re: most efficient way to save/restore 6502 registers wssimms@gmail.com - 2016-02-04 21:20 -0800
| From | Mark Lemmert <mark.lemmert@gmail.com> |
|---|---|
| Date | 2016-02-04 11:41 -0800 |
| Subject | most efficient way to save/restore 6502 registers |
| Message-ID | <61723ee6-c434-48d0-9bb0-bd44b545c922@googlegroups.com> |
I am wondering if anybody knows why the most Apple II assembly subroutines save/restore registered via the stack (method 1 below), instead of using variables (method 2 below)? And, what are the advantages and disadvantages are for each method? Thanks a lot for any insights! I'm interested in knowing because when writing code where speed is a priority tend to use variables and wondering if I'm missing an important consideration. The parenthetical numbers in the comment fields below are the clock cycles for each opcode according to the following reference guide (it's on an atari site but since both Apple and Atari use 6502 my understanding is that the opcodes cycle times are the same) http://www.atarimax.com/jindroush.atari.org/aopc.html Here is what I've come up with so far: Advantages (Stack) ====================== Less Memory Slightly better code readability (I think mainly because it's the standard so it's immediately obvious what's going on) Advantages (Variables) ======================= Speed =====METHOD 1 (Stack)===== ;SAVE REGISTERS TXA ;(2) PHA ;(3) TYA ;(2) PHA ;(3) <SUBROUTINE CODE> ;RESTORE REGISTERS PLA ;(4) TAY ;(2) PLA ;(4) TAX ;(2) Total clock cycles: !22 Total Bytes: !16 =====METHOD 1 (Variables)===== ;SAVE REGISTERS STX SAVED.XREG.LOCAL ;(4) STY SAVED.YREG.LOCAL ;(4) <SUBROUTINE CODE> ;RESTORE REGISTERS LDX SAVED.XREG.LOCAL ;(4) LDY SAVED.YREG.LOCAL ;(4) Total clock cycles: !16 Total bytes !24 (for code) + 2 (for variables) = !26
[toc] | [next] | [standalone]
| From | Scott Hemphill <hemphill@hemphills.net> |
|---|---|
| Date | 2016-02-04 15:31 -0500 |
| Message-ID | <87mvrgi5fa.fsf@hemphills.net> |
| In reply to | #2204 |
Mark Lemmert <mark.lemmert@gmail.com> writes: > I am wondering if anybody knows why the most Apple II assembly > subroutines save/restore registered via the stack (method 1 below), > instead of using variables (method 2 below)? > > And, what are the advantages and disadvantages are for each method? > > Thanks a lot for any insights! (1) I think you pretty much covered it. Note that if you do a lot of saving/restoring, you could (with both schemes) reduce the per instance memory usage by doing this: JSR XYSAVE ... JSR XYRESTORE You could even omit the call to XYRESTORE if XYSAVE manipulates the stack by putting the address to XYRESTORE on it, so that the RET from your subroutine automatically restores the registers. (2) If your subroutine calls itself recursively, you need to store the registers on a stack. (3) If your subroutine doesn't know which memory banks are switched in (e.g. when processing an interrupt) then you may not want to store the registers in memory. (4) Saving the registers in memory allows you to restore them multiple times. Scott -- Scott Hemphill hemphill@alumni.caltech.edu "This isn't flying. This is falling, with style." -- Buzz Lightyear
[toc] | [prev] | [next] | [standalone]
| From | Mark Lemmert <mark.lemmert@gmail.com> |
|---|---|
| Date | 2016-02-04 19:22 -0800 |
| Message-ID | <9daa1cb8-14a2-4e10-b3c5-785c1d53799e@googlegroups.com> |
| In reply to | #2205 |
On Thursday, February 4, 2016 at 2:31:07 PM UTC-6, Scott Hemphill wrote: Scott, Thanks for the reply! (1) Great idea. Perfect for programs with plenty of speed and tight on memory. (2)-(4): This is just the kind of insight I was hoping to gain...I figured there was probably some more advanced bigger picture I was missing on the stack and these examples nail it. Thanks again. > Mark Lemmert writes: > > > I am wondering if anybody knows why the most Apple II assembly > > subroutines save/restore registered via the stack (method 1 below), > > instead of using variables (method 2 below)? > > > > And, what are the advantages and disadvantages are for each method? > > > > Thanks a lot for any insights! > > (1) I think you pretty much covered it. Note that if you do a lot of > saving/restoring, you could (with both schemes) reduce the per instance > memory usage by doing this: > > JSR XYSAVE > ... > JSR XYRESTORE > > You could even omit the call to XYRESTORE if XYSAVE manipulates the > stack by putting the address to XYRESTORE on it, so that the RET from > your subroutine automatically restores the registers. > > (2) If your subroutine calls itself recursively, you need to store the > registers on a stack. > > (3) If your subroutine doesn't know which memory banks are switched in > (e.g. when processing an interrupt) then you may not want to store the > registers in memory. > > (4) Saving the registers in memory allows you to restore them multiple > times. > > Scott
[toc] | [prev] | [next] | [standalone]
| From | Michael Barry <barrym95838@yahoo.com> |
|---|---|
| Date | 2016-02-04 20:21 -0800 |
| Message-ID | <63f8f033-1491-414f-8855-dcf92d08b695@googlegroups.com> |
| In reply to | #2207 |
On Thursday, February 4, 2016 at 7:22:50 PM UTC-8, Mark Lemmert wrote:
> ...
If your subroutines are in RAM, and you do not need them to be re-
entrant and/or recursive, you could try self-modifying code:
subroutine:
stx subzzz-3
sty subzzz-1
...
...
ldx #00 ; dummy operand
ldy #00 ; dummy operand
subzzz:
rts
It's just as fast as zero-page variables, and trades a couple
of bytes of zero-page for a couple of bytes of code space.
Mike B.
[toc] | [prev] | [next] | [standalone]
| From | wssimms@gmail.com |
|---|---|
| Date | 2016-02-04 21:20 -0800 |
| Message-ID | <ab89178a-01c2-47c1-ba8e-edbbd736871a@googlegroups.com> |
| In reply to | #2209 |
Am Freitag, 5. Februar 2016 13:21:49 UTC+9 schrieb Michael Barry:
> On Thursday, February 4, 2016 at 7:22:50 PM UTC-8, Mark Lemmert wrote:
> > ...
>
> If your subroutines are in RAM, and you do not need them to be re-
> entrant and/or recursive, you could try self-modifying code:
>
> subroutine:
> stx subzzz-3
> sty subzzz-1
> ...
> ...
> ldx #00 ; dummy operand
> ldy #00 ; dummy operand
> subzzz:
> rts
>
> It's just as fast as zero-page variables, and trades a couple
> of bytes of zero-page for a couple of bytes of code space.
>
> Mike B.
First off, I am a big fan of self-modifying code on 6502 processors. I like this example of register saving and reloading and I also like to use self-modifying code for manipulating things through pointers. For example, to copy memory.
Second off, I am a fan of using 65c02 opcodes. Given than enhanced IIes, IIcs, and IIgses are the vast majority of machines still being actively used, it seems reasonable to do so, in my opinion. Therefore:
; Save Registers
pha
phy
phx
...
; Restore Registers
plx
ply
pla
rts
works great for me.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.sys.apple2.programmer
csiph-web