6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sat Nov 23, 2024 10:39 pm

All times are UTC




Post new topic Reply to topic  [ 24 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Fri Jul 31, 2020 4:19 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
dmsc wrote:
The main problem with many registers is that you need to save the registers on interrupts (making interrupts slow)....

Well, no you don't. That's purely a design decision, and I would consider it one of the brilliant innovations in the 6502 that it doesn't save the entire register file when responding to an interrupt.

Apparently I'm not alone in this; the designers of the 6809 liked the idea enough that they added a second maskable interrupt, FIRQ, that worked in the same way.

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 05, 2020 2:06 pm 
Offline
User avatar

Joined: Tue Oct 25, 2016 8:56 pm
Posts: 362
cjs wrote:
dmsc wrote:
The main problem with many registers is that you need to save the registers on interrupts (making interrupts slow)....

Well, no you don't. That's purely a design decision, and I would consider it one of the brilliant innovations in the 6502 that it doesn't save the entire register file when responding to an interrupt.

Apparently I'm not alone in this; the designers of the 6809 liked the idea enough that they added a second maskable interrupt, FIRQ, that worked in the same way.


Indeed, its such a good idea that ARM and x86 behave essentially the same way: they save (via one method or another) only those registers that must be saved, and leave the ISR itself to save any others that it needs to use. Of course, in practice, you'll need to save at least one or two general purpose registers or your ISR is unlikely to be able to do anything useful (in the case of 6502, I would say at least the accumulator and one index register), but you as the programmer get to decide what resources you need and what the trade-off is versus the required interrupt servicing delay. For example, I doubt that any ARM ISR actually saves all 14 general purpose registers since for the types of jobs you should be doing in an ISR that would be pointless: I've seen entire ARM software packages that never touch some of the registers at all, let alone in an ISR, because there just aren't that many variables that need to be loaded into the CPU at any given moment. Now that I think about it, if you have some spare registers that you're not otherwise using, that'd be a really good way to speed up your ISR: just have it use those registers that the rest of the software doesn't use, that way you never have to worry about saving and restoring them at all (unless you need the ISR to be re-entrant).

All that being said, in the specific case of the 6502 architecture I feel like it would be nice if the interrupt process saved and restored the accumulator for you because there is essentially no way of doing anything useful without it and it would save a couple of cycles per interrupt. I vaguely remember reading somewhere that it was originally intended that it would but the necessary circuitry wouldn't fit or some such.

_________________
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: Wed Aug 05, 2020 3:00 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
Quote:
if you have some spare registers that you're not otherwise using, that'd be a really good way to speed up your ISR: just have it use those registers that the rest of the software doesn't use, that way you never have to worry about saving and restoring them at all
Yup -- I had an MSP430 project that worked that way. Honestly, it was so easy it felt a little creepy... The failure to save/restore any reg's left me feeling as if I'd broken the rules! :P

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 06, 2020 2:25 pm 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
Alarm Siren wrote:
All that being said, in the specific case of the 6502 architecture I feel like it would be nice if the interrupt process saved and restored the accumulator for you because there is essentially no way of doing anything useful without it and it would save a couple of cycles per interrupt. I vaguely remember reading somewhere that it was originally intended that it would but the necessary circuitry wouldn't fit or some such.

Actually, the NMOS 6502 does have number of instructions that neither read nor change registers. These include INC/DEC in direct or extended address modes (oops...I think I mean "zero page" and "absolute" there—too much 6800 on my brain at the moment), and shift instructions on memory locations (which affect the flags, but those are automatically saved and restored). So with some careful hardware design you could probably do at least checks of what needs to be done during the interrupt without needing to save any registers.

And of course the Rockwell 65C02 adds SMB/RMB/BBR bit manipulation and test instructions that extend one's abilities to do the above kind of stuff.

_________________
Curt J. Sampson - github.com/0cjs


Top
 Profile  
Reply with quote  
PostPosted: Sun Aug 09, 2020 2:25 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 704
Location: North Tejas
BigEd wrote:
The clock speed of the CPU is not as important as the rate at which memory accesses can be made: hence a lot of the confusion with the Z80 vs 6502, and indeed the 1802. It's memory cycles which should be counted.


I have been playing with my toy Pascal compilers. This is some of the generated code...

For the 6502:

Code:
                          00084 ; 00009     A := 1;
 0B09 A2 01           [2] 00085          ldx    #1
 0B0B A9 00           [2] 00086          lda    #0
 0B0D 8E 0E71         [4] 00087          stx    A_
 0B10 8D 0E72         [4] 00088          sta    A_+1
                          00089 ; 00010     B := A + 1;
 0B13 18              [2] 00090          clc
 0B14 AD 0E71         [4] 00091          lda    A_
 0B17 69 01           [2] 00092          adc    #1
 0B19 AA              [2] 00093          tax
 0B1A AD 0E72         [4] 00094          lda    A_+1
 0B1D 69 00           [2] 00095          adc    #0
 0B1F 8E 0E73         [4] 00096          stx    B_
 0B22 8D 0E74         [4] 00097          sta    B_+1
                          00098 ; 00011     A := B;
 0B25 AE 0E73         [4] 00099          ldx    B_
 0B28 AD 0E74         [4] 00100          lda    B_+1
 0B2B 8E 0E71         [4] 00101          stx    A_
 0B2E 8D 0E72         [4] 00102          sta    A_+1
                          00103 ; 00012     C := A + B;
 0B31 18              [2] 00104          clc
 0B32 AD 0E71         [4] 00105          lda    A_
 0B35 6D 0E73         [4] 00106          adc    B_
 0B38 AA              [2] 00107          tax
 0B39 AD 0E72         [4] 00108          lda    A_+1
 0B3C 6D 0E74         [4] 00109          adc    B_+1
 0B3F 8E 0E75         [4] 00110          stx    C_
 0B42 8D 0E76         [4] 00111          sta    C_+1
                          00112 ; 00013     writeln('Hello world.');
 0B45 A2 64           [2] 00113          ldx    #<S_00000
 0B47 A9 0E           [2] 00114          lda    #>S_00000
 0B49 20 0CBE         [6] 00115          jsr    WriteString
 0B4C 20 0CF8         [6] 00116          jsr    PCRLF


For the 8080:

Code:
                          00029 ; 00009     A := 1;
 0100 21 0001        [10] 00030         lxi     H,1
 0103 22 01F3        [16] 00031         shld    A_
                          00032 ; 00010     B := A + 1;
 0106 2A 01F3        [16] 00033         lhld    A_
 0109 11 0001        [10] 00034         lxi     D,1
 010C 19             [10] 00035         dad     D
 010D 22 01F5        [16] 00036         shld    B_
                          00037 ; 00011     A := B;
 0110 2A 01F5        [16] 00038         lhld    B_
 0113 22 01F3        [16] 00039         shld    A_
                          00040 ; 00012     C := A + B;
 0116 2A 01F3        [16] 00041         lhld    A_
 0119 EB              [4] 00042         xchg
 011A 2A 01F5        [16] 00043         lhld    B_
 011D 19             [10] 00044         dad     D
 011E 22 01F7        [16] 00045         shld    C_
                          00046 ; 00013     writeln('Hello world.');
 0121 21 01D6        [10] 00047         lxi     H,S_00000
 0124 CD 019C        [17] 00048         call    WriteString
 0127 CD 018D        [17] 00049         call    PCRLF


And for the 6800:

Code:
                          00068 ; 00009     A := 1;
 010A CE 0001         [3] 00069          ldx    #1
 010D FF 02FD         [6] 00070          stx    A_
                          00071 ; 00010     B := A + 1;
 0110 F6 02FE         [4] 00072          ldab   A_+1
 0113 CB 01           [2] 00073          addb   #1
 0115 B6 02FD         [4] 00074          ldaa   A_
 0118 89 00           [2] 00075          adca   #0
 011A F7 0300         [5] 00076          stab   B_+1
 011D B7 02FF         [5] 00077          staa   B_
                          00078 ; 00011     A := B;
 0120 FE 02FF         [5] 00079          ldx    B_
 0123 FF 02FD         [6] 00080          stx    A_
                          00081 ; 00012     C := A + B;
 0126 F6 02FE         [4] 00082          ldab   A_+1
 0129 FB 0300         [4] 00083          addb   B_+1
 012C B6 02FD         [4] 00084          ldaa   A_
 012F B9 02FF         [4] 00085          adca   B_
 0132 F7 0302         [5] 00086          stab   C_+1
 0135 B7 0301         [5] 00087          staa   C_
                          00088 ; 00013     writeln('Hello world.');
 0138 CE 02F0         [3] 00089          ldx    #S_00000
 013B BD 01A2         [9] 00090          jsr    WriteString
 013E BD 01CA         [9] 00091          jsr    PCRLF


There is no optimization at this time other than some simple things which can be done while parsing.

Obvious opportunities for

Code:
A + 1


are

Code:
ldx     A_
inx


for the 6800

and

Code:
lhld    A_
inx     H


for the 8080.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 11, 2020 11:18 am 
Offline

Joined: Tue Sep 03, 2002 12:58 pm
Posts: 336
Would a 32 bit evolution of 65816 stay accumulator based?

In one sense, that question has already been answered by the 65832, and the answer was "yes". You could take the fate of that design as an indication that this was the wrong answer. The industry as a whole as taken a totally different route, and for good reasons. A respectable number of general purpose registers is pretty much essential if you want to make a competitive processor for desktop computers at any point past the early 1980s.

Would an evolution of the 6502 with a respectable number of general purpose registers still be a '6502'? That depends on what you think the essence of the 6502 is. If the essential factor is the ability to run 6502 binaries without modification (or without too much), then yes. If you want it to still feel like a 6502 in some vague way that gives us oldies all the nostalgia, then probably no.

My (very slowly progressing) 65020 project is almost binary compatible; I think there was only one change I needed to get Microsoft BASIC running. It has 12 almost but not quite general purpose registers. And it does not feel like a 6502. Part of that is deliberate - I wanted something that could have been an alternative to the 68000, and although still losing, still put up a decent fight against the ARM. Compatibility has forced a few quirks, but on the whole it feels like the awkward younger sibling of the ARM, MIPS and PowerPC.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 11, 2020 1:44 pm 
Offline
User avatar

Joined: Fri Dec 11, 2009 3:50 pm
Posts: 3367
Location: Ontario, Canada
John West wrote:
It has 12 almost but not quite general purpose registers.
Hmmm, intriguing! I'll be interested to hear more about this project, whenever you feel ready. Among other challenges, you have the question of instruction encoding. The fact you're addressing more registers while preserving (almost) binary compatibility makes me suspect you're using prefix bytes... but I could be wrong; other solutions exist.

-- Jeff

_________________
In 1988 my 65C02 got six new registers and 44 new full-speed instructions!
https://laughtonelectronics.com/Arcana/ ... mmary.html


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 11, 2020 3:02 pm 
Offline

Joined: Tue Sep 03, 2002 12:58 pm
Posts: 336
Dr Jefyll wrote:
John West wrote:
It has 12 almost but not quite general purpose registers.
Hmmm, intriguing! I'll be interested to hear more about this project, whenever you feel ready. Among other challenges, you have the question of instruction encoding. The fact you're addressing more registers while preserving (almost) binary compatibility makes me suspect you're using prefix bytes... but I could be wrong; other solutions exist.


I've given each byte an extra 8 bits that the 6502 didn't know about, and arranged the instruction set so that if these new bits are all 0 it behaves like a 6502. So it sort of is using prefix bytes, only everything, including operands, gets them. Some of the extra bits are used to select different registers (there are 4 of each of A, X, and Y). Two of them control the data width (8, 16 or 32 bit operations). One is used to choose a variant of the instruction: ADC becomes ADD without carry. Two byte addresses, which the 6502 thought were only 16 bit, now have 32 bits.

There's an old and not very good description at http://c640.blogspot.com/2018/06/the-65020.html, and some example code at http://c640.blogspot.com/2018/07/some-65020-code.html. I'm currently working on the user manual for the processor, so maybe you'll get to see a better description sometime this year. I should be working on a testbed for the ALU, but motivation for VHDL coding is very hard to find.


Top
 Profile  
Reply with quote  
PostPosted: Thu Sep 24, 2020 6:07 pm 
Offline

Joined: Sat Jul 09, 2016 6:01 pm
Posts: 180
dmsc wrote:
But the same is the reason a 6502 based design can't be made faster. For example, look at an instruction like "LDA (12), X". That instruction reads from one register (X), reads from three memory locations (12, 13 and the address calculated from those) and writes to the accumulator. That means that you can't execute that instruction in less than 3 cycles (one for each memory access), even discounting the reading of the instruction word.

If we move the ZP to registers - http://anycpu.org/forum/viewtopic.php?f ... 5890#p5833 - we can get only 2 cycles which matches timings of the best processors.

_________________
my blog about processors


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

All times are UTC


Who is online

Users browsing this forum: No registered users and 17 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: