Do registers really make code easier to write?
Do registers really make code easier to write?
This past week I've been thinking a lot about designing my own CPU. I've been testing out things like 2 operand mem-reg instructions and 3 operand reg-reg instructions to see what I like best, and it occurred to me that registers are very confusing to keep tracked of. With the 65816, I've gotten used to giving every memory address a label name, so it is easy to keep track. If memory address can be labeled, could registers be labeled too?
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Do registers really make code easier to write?
Even a relatively simple assembler should be able to equate a label with a register name, but it would still be a bit confusing in a large or complex program, because there would be an almost certain need for overlapping labels.
Here is a short SWEET-16 example, using San Bergmans' assembler. Note the register equates starting around line #40:
Mike
Here is a short SWEET-16 example, using San Bergmans' assembler. Note the register equates starting around line #40:
Code: Select all
0000- 5 ;-----------------------------------------------------;
0000- 6 ; BEER SONG FOR THE SWEET16 PSEUDO-PROCESSOR ;
0000- 7 ; BY BARRYM 2011-05-21 ;
0000- 8 ;-----------------------------------------------------;
0000- 9 ; THANKS TO SBPROJECTS.COM FOR LOTS OF VALUABLE INFO ;
0000- 10 ; AND A VERY NICE ASSEMBLER!! ;
0000- 11 ; THE SWEET16 PROCESSOR WAS CREATED BY STEVE WOZNIAK ;
0000- 12 ; IN 1977 TO HELP HIM WRITE COMPACT (BUT SLOWER) ;
0000- 13 ; 16-BIT CODE ON HIS NEW BABY, THE APPLE II. HE ;
0000- 14 ; NEVER BUILT IT IN HARDWARE, BUT INSTEAD CREATED ;
0000- 15 ; A NIFTY LITTLE 372-BYTE INTERPRETER AND BURNED ;
0000- 16 ; IT INTO THE ROM OF THE ORIGINAL INTEGER BASIC ;
0000- 17 ; APPLE II. ;
0000- 18 ; SWEET16 CODE AND 6502 CODE CAN CO-EXIST PEACEFULLY ;
0000- 19 ; IN AN APPLE II MACHINE LANGUAGE PROGRAM; A 6502 ;
0000- 20 ; 'JSR $F689' IMMEDIATELY PRECEDES A BLOCK OF IN- ;
0000- 21 ; LINE SWEET16 INSTRUCTIONS AND A SWEET16 'RTN' ;
0000- 22 ; SWITCHES BACK TO 6502 MODE, WHICH MUST BE DONE ;
0000- 23 ; AT OR BEFORE PROGRAM COMPLETION. THE ORIGINAL ;
0000- 24 ; APPLE II HAD AN UPPER-CASE 40-COLUMN DISPLAY AS ;
0000- 25 ; STANDARD EQUIPMENT, SO THE OFFICIAL SONG LYRICS ;
0000- 26 ; ARE ADJUSTED ACCORDINGLY. ;
0000- 27 ; NOTE: 'ADD' AND 'SUB' ARE BUILT-IN 6502 MACROS IN ;
0000- 28 ; THE CURRENT VERSION OF THIS ASSEMBLER AND WILL ;
0000- 29 ; NOT ASSEMBLE TO THE CORRECT SWEET16 OPCODES (USE ;
0000- 30 ; '.DA #$AX' FOR 'ADD X' & '.DA #$BX' FOR 'SUB X') ;
0000- 31 ;-----------------------------------------------------;
0000- 32 ; CONSTANT EQUATES ;
0000- 33 ;-----------------------------------------------------;
F689- 34 SWEET16 = $F689 ROM: WOZ' INTERPRETER
E51B- 35 BIN2ASC = $E51B ROM: PRINT UNSIGNED16
FDED- 36 PUTCHAR = $FDED ROM: PRINT CHARACTER
0063- 37 MAXB = 99 MUST BE IN [1..65535]
0000- 38 ;-----------------------------------------------------;
0000- 39 ; REGISTER EQUATES ;
0000- 40 ;-----------------------------------------------------;
0000- 41 ACC = $0 SWEET16 MAIN ACCUMULATOR
0001- 42 BEER = $1 BEER COUNTER
0002- 43 TYPE = $2 SUBPHRASE TYPE TEMP
0003- 44 PTR = $3 TEXT POINTER
000C- 45 STK = $C SWEET16 STACK POINTER
0000- 46 ;-----------------------------------------------------;
0000- 47 ; MAIN PROGRAM ;
0000- 48 ;-----------------------------------------------------;
0E00- 49 .OR $0E00
0E00-20 89 F6 50 MAIN JSR SWEET16 ENTER SWEET16 MODE
0E03-1C 00 01 51 SET STK,$0100 INIT SWEET16 STACK POINTER
0E06-11 63 00 52 SET BEER,MAXB BEER = MAXB
0E09-B0 53 .DA #$B0 'SUB ACC' (TYPE=0)
0E0A-0C 07 54 BS PRSONG PRINT THE ENTIRE SONG
0E0C-00 55 RTN RETURN TO 6502 MODE
0E0D-60 56 RTS EXIT
0E0E- 57 ;-----------------------------------------------------;
0E0E- 58 ; PRINT ALL EXCEPT THE LAST SENTENCE ;
0E0E- 59 ;-----------------------------------------------------;
0E0E-13 5C 0E 60 BEERME SET PTR,TAKE EMIT "TAKE ONE ... IT AROUND,"
0E11-0C 12 61 BS PRBOB EMIT " ... ON THE WALL."
0E13-13 7D 0E 62 PRSONG SET PTR,CR EMIT BLANK LINE
0E16-0C 0D 63 BS PRBOB EMIT " ... ON THE WALL";
0E18-F0 64 DCR ACC TYPE = -1
0E19-13 7C 0E 65 SET PTR,COMCR EMIT ","
0E1C-0C 07 66 BS PRBOB EMIT " ... OF BEER."
0E1E-E0 67 INR ACC TYPE = +1
0E1F-F1 68 DCR BEER BEER = BEER - 1
0E20-09 EC 69 BNM1 BEERME IF BEER <> -1 THEN BEERME
0E22- 70 ;-----------------------------------------------------;
0E22- 71 ; SET UP LAST SENTENCE AND FALL THRU ;
0E22- 72 ;-----------------------------------------------------;
0E22-11 63 00 73 SET BEER,MAXB BEER = MAXB
0E25- 74 ; EMIT "GO TO ... BUY SOME MORE,"
0E25- 75 ;-----------------------------------------------------;
0E25- 76 ; PRINT A PROPERLY PUNCTUATED BOTTLE SUB-PHRASE ;
0E25- 77 ; (ENTRY): PTR CONTAINS PRE-STRING POINTER, ACC ;
0E25- 78 ; CONTAINS SUB-PHRASE TYPE (0 = " ... THE WALL", ;
0E25- 79 ; -1 = " ... OF BEER.", +1 = " ... THE WALL.") ;
0E25- 80 ; (EXIT): ACC IS CLEARED ;
0E25- 81 ;-----------------------------------------------------;
0E25-32 82 PRBOB ST TYPE
0E26-0C 25 83 BS PUTS EMIT PRE-STRING
0E28-21 84 LD BEER IF BEER = 0 THEN
0E29-06 0E 85 BZ PRBOTT EMIT "NO MORE";
0E2B-00 86 RTN IF BEER > 0 THEN
0E2C-A5 03 87 LDA $03 RETURN TO 6502 MODE JUST
0E2E-A6 02 88 LDX $02 LONG ENOUGH TO CONVERT AND
0E30-20 1B E5 89 JSR BIN2ASC EMIT BEER TO ACTIVE OUTPUT
0E33-20 8C F6 90 JSR SWEET16+3
0E36-13 86 0E 91 SET PTR,BOTTL
0E39-0C 12 92 PRBOTT BS PUTS EMIT " ... BOTTLE";
0E3B-F1 93 DCR BEER
0E3C-07 01 94 BNZ NEQ1 IF BEER = 1 THEN
0E3E-E3 95 INR PTR SKIP OVER THE "S"
0E3F-E1 96 NEQ1 INR BEER
0E40-0C 0B 97 BS PUTS EMIT " ... OF BEER";
0E42-22 98 LD TYPE
0E43-08 05 99 BM1 NOWALL IF TYPE >= 0 THEN
0E45-0C 06 100 BS PUTS EMIT " ON THE WALL";
0E47-22 101 LD TYPE
0E48-06 11 102 BZ KPUT IF TYPE <> 0 THEN
0E4A-13 A5 0E 103 NOWALL SET PTR,DOTCR EMIT "."
0E4D- 104 ;-----------------------------------------------------;
0E4D- 105 ; PRINT A NULL-TERMINATED STRING @ PTR ;
0E4D- 106 ; (ENTRY): PTR POINTS TO THE START OF THE STRING ;
0E4D- 107 ; (EXIT): PTR POINTS TO THE NEXT STRING IN MEMORY, ;
0E4D- 108 ; ACC IS CLEARED ;
0E4D- 109 ;-----------------------------------------------------;
0E4D-43 110 PUTS LD @PTR GRAB CHAR @ PTR AND ADVANCE PTR
0E4E-06 0B 111 BZ KPUT IF CHAR <> NULL THEN
0E50-00 112 RTN ESC TO 6502 MODE
0E51-A5 00 113 LDA $00 JUST LONG ENOUGH TO EMIT
0E53-20 ED FD 114 JSR PUTCHAR THE CHAR TO ACTIVE OUTPUT
0E56-20 8C F6 115 JSR SWEET16+3
0E59-01 F2 116 BR PUTS LOOP UNTIL NULL
0E5B-0B 117 KPUT RS RETURN
0E5C- 118 ;-----------------------------------------------------;
0E5C- 119 ; OPTIMIZED SONG LYRIC STRING ;
0E5C- 120 ;-----------------------------------------------------;
0E5C-D4 C1 CB C5
0E60-A0 CF CE C5
0E64-A0 C4 CF D7
0E68-CE A0 C1 CE
0E6C-C4 A0 D0 C1
0E70-D3 D3 A0 C9
0E74-D4 A0 C1 D2
0E78-CF D5 CE C4 121 TAKE .AS -"TAKE ONE DOWN AND PASS IT AROUND"
0E7C-AC 122 COMCR .AS -","
0E7D-8D 00 123 CR .AZ -#13
0E7F-CE CF A0 CD
0E83-CF D2 C5 124 .AS -"NO MORE"
0E86-A0 C2 CF D4
0E8A-D4 CC C5 00 125 BOTTL .AZ -" BOTTLE"
0E8E-D3 A0 CF C6
0E92-A0 C2 C5 C5
0E96-D2 00 126 .AZ -"S OF BEER"
0E98-A0 CF CE A0
0E9C-D4 C8 C5 A0
0EA0-D7 C1 CC CC
0EA4-00 127 .AZ -" ON THE WALL"
0EA5-AE 8D 00 128 DOTCR .AZ -".",#13
0EA8-C7 CF A0 D4
0EAC-CF A0 D4 C8
0EB0-C5 A0 D3 D4
0EB4-CF D2 C5 A0
0EB8-C1 CE C4 A0
0EBC-C2 D5 D9 A0
0EC0-D3 CF CD C5
0EC4-A0 CD CF D2
0EC8-C5 AC 8D 00 129 .AZ -"GO TO THE STORE AND BUY SOME MORE,",#13
0ECC- 130 .EN
- BigDumbDinosaur
- Posts: 9425
- Joined: 28 May 2009
- Location: Midwestern USA (JB Pritzker’s dystopia)
- Contact:
Re: Do registers really make code easier to write?
Aaendi wrote:
This past week I've been thinking a lot about designing my own CPU. I've been testing out things like 2 operand mem-reg instructions and 3 operand reg-reg instructions to see what I like best, and it occurred to me that registers are very confusing to keep tracked of. With the 65816, I've gotten used to giving every memory address a label name, so it is easy to keep track. If memory address can be labeled, could registers be labeled too?
x86? We ain't got no x86. We don't NEED no stinking x86!
Re: Do registers really make code easier to write?
For assembly: if any opcode mnemonic includes a reference to the register (INX, DEY, PHA) the answer is no. If registers are only referred to by operands, the answer is yes. For example the AVR assembler has a .DEF statement (.DEF myregister = r21).
6502 sources on GitHub: https://github.com/Klaus2m5
Re: Do registers really make code easier to write?
The question could become: are registers an optimisation (or a technical compromise, if you prefer to look at it like that) or do they add instead make possible things which would be imossible without them?
I suspect the answer is the former. Ie they simplify the design and act as a sort of cache, albeit one managed by the programmer.
I'd be very surprised if there aren't real CPUs available which have no registers. But I doubt they'd have gained much real-world traction, because in the real-world optimisations (for example, against runtime speed) are important.
I suspect the answer is the former. Ie they simplify the design and act as a sort of cache, albeit one managed by the programmer.
I'd be very surprised if there aren't real CPUs available which have no registers. But I doubt they'd have gained much real-world traction, because in the real-world optimisations (for example, against runtime speed) are important.
8 bit fun and games: https://www.aslak.net/
- barrym95838
- Posts: 2056
- Joined: 30 Jun 2013
- Location: Sacramento, CA, USA
Re: Do registers really make code easier to write?
It's difficult for me to imagine an architecture that doesn't have at least an accumulator, instruction pointer, memory access register and memory data register, but I am willing to bet that it's possible to construct a stored-program, Turing-complete machine with less. It really boils down to whether or not a programmer is comfortable with its assembly language, and whether or not it has adequate performance for the job at hand.
CPU architectures that are not human-friendly may be compiler-friendly, or vice-versa. The favorites are usually both. I have the most fun and highest comfort-level with four to eight GP registers, but I may be in the minority here.
Mike
CPU architectures that are not human-friendly may be compiler-friendly, or vice-versa. The favorites are usually both. I have the most fun and highest comfort-level with four to eight GP registers, but I may be in the minority here.
Mike
-
teamtempest
- Posts: 443
- Joined: 08 Nov 2009
- Location: Minnesota
- Contact:
Re: Do registers really make code easier to write?
I suppose it would be possible create a processor whose every instruction referenced memory. So:
But even if there are no programmer-available register, the processor will almost certainly need some "hidden" internal registers to handle addressing, arithmetic and logic operations. The operands still have to be fetched from memory, operated on, and stored back, even if the process is invisible to the user.
Code: Select all
mov absolute0,#mylabel
mov absolute1,#1000
loop:
mov (absolute0),#$00
inc absolute0
dec absolute1
bne absolute1,loop
rts
- kiamnetrem
- Posts: 6
- Joined: 27 Aug 2014
Re: Do registers really make code easier to write?
Complete and useful CPUs can work without registers as part of the machine instructions. Once instance is the Zylin CPU core, which is a tiny 32-bit processor designed to be synthesized into FPGAs with complete support by the GCC compiler. It's stack based.
A nice overview is given here: http://retroramblings.net/?p=434
A nice overview is given here: http://retroramblings.net/?p=434
-
ElEctric_EyE
- Posts: 3260
- Joined: 02 Mar 2009
- Location: OH, USA
Re: Do registers really make code easier to write?
kiamnetrem wrote:
Complete and useful CPUs can work without registers as part of the machine instructions. Once instance is the Zylin CPU core, which is a tiny 32-bit processor designed to be synthesized into FPGAs with complete support by the GCC compiler. It's stack based...
Personally, I always felt limited by the 6502's X and Y registers and one accumulator. All the TYA, PLA, PHX's etc., while not a pain to follow in code, does take away from the overall machine code's speed. More registers would seem that less of the stack would be used...
One thing lacking in the 65Or16 that I would have liked for my 'take' on a better 6502, i.e. 65Org16, would have been simple SWAP opcodes to accomodate the 16 accumulators and x,y,w registers. But it does have the ability to transfer a value from any of the 16 accumulators/3 registers amongst themselves. Obviously this is not a SWAP though.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Do registers really make code easier to write?
ElEctric_EyE wrote:
kiamnetrem wrote:
Complete and useful CPUs can work without registers as part of the machine instructions. Once instance is the Zylin CPU core, which is a tiny 32-bit processor designed to be synthesized into FPGAs with complete support by the GCC compiler. It's stack based...
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
-
ElEctric_EyE
- Posts: 3260
- Joined: 02 Mar 2009
- Location: OH, USA
Re: Do registers really make code easier to write?
GARTHWILSON wrote:
... a stack processor's native language is basically Forth, ie, that it takes very little processing for a compiler to turn Forth into the machine language; so I would venture to say that yes, it's easier to write. These are incredible performers considering their hardware simplicity and clock speeds. The stacks are onboard though, each with its own bus, so they don't have to go out on the normal memory bus for stack access, and accesses can be done on multiple buses at the same time.
Forgive me, I've been away from 6502 (even 65Org16) software for a few months.
Re: Do registers really make code easier to write?
I just tried coding psuedo-assembly for a CPU with 4 general purpose registers (A, B, X and Y), ARM-style shifting, and 6809-style mnemonics and so far it looks like I would be comfortable programming it.
This code is supposed to check what BG tile a pixel overlaps. It seems like enough general purpose registers to make it easier than the 65xx, but not enough to be difficult to keep track of.
Code: Select all
ldy {x_pixel},(x)
lda y >> 4
anda #$001f
ldb {y_pixel},(x)
andb #$01f0
ora b << 1
andy #$fe00
ora y << 1
lda {bg_map},(a)
anda #$03ff
lda {collision_data},(a)
Last edited by Aaendi on Tue Sep 02, 2014 11:42 am, edited 1 time in total.
Re: Do registers really make code easier to write?
Having more registers available (to a point) makes it easier to get performance from a high-level compiled language like C or C++.
It's been studied, registers vs stack vs accumulator architectures.
They added more regs (r8-r15) to the x86 arch. to improve performance for some software.
Depending on what the target application of the processor is one may want more or fewer registers.
The 6502 works great with just .A, .X. and .Y for 6502 style apps.
If one isn't planning on using a high-level language compiler then it may not make that much difference how many registers are available. I wrote most of a bootrom in assembler using only four registers. Even though more registers were available it would make little difference to performance.
I use 256 regs for my latest cpu; but I intend on using compiled languages with it.
64 bit cpu's seem to have more regs. (IA64, MMIX, ).
So the answer is: I don't think registers make code easier to write; they can just enhance performance sometimes.
It's been studied, registers vs stack vs accumulator architectures.
They added more regs (r8-r15) to the x86 arch. to improve performance for some software.
Depending on what the target application of the processor is one may want more or fewer registers.
The 6502 works great with just .A, .X. and .Y for 6502 style apps.
If one isn't planning on using a high-level language compiler then it may not make that much difference how many registers are available. I wrote most of a bootrom in assembler using only four registers. Even though more registers were available it would make little difference to performance.
I use 256 regs for my latest cpu; but I intend on using compiled languages with it.
64 bit cpu's seem to have more regs. (IA64, MMIX, ).
So the answer is: I don't think registers make code easier to write; they can just enhance performance sometimes.
- GARTHWILSON
- Forum Moderator
- Posts: 8773
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: Do registers really make code easier to write?
ElEctric_EyE wrote:
GARTHWILSON wrote:
... a stack processor's native language is basically Forth, ie, that it takes very little processing for a compiler to turn Forth into the machine language; so I would venture to say that yes, it's easier to write. These are incredible performers considering their hardware simplicity and clock speeds. The stacks are onboard though, each with its own bus, so they don't have to go out on the normal memory bus for stack access, and accesses can be done on multiple buses at the same time.
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?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: Do registers really make code easier to write?
I use a macro that I named 'mb' (Move Byte). It can output the correct code to move a byte from one location to to another:
You can probably guess why code is output. Also, it can handle:
In which case you could name register A and have it be useful:
But for standard 6502, I don't think naming registers can really help much.
You might be able to:
But that might be pretty confusing over a comment.
Code: Select all
; move from one memory location to another, use A by default:
mb foo := bar
; move using .X:
mb x, foo := bar
Code: Select all
mb a := bar ; will output 'lda bar'
mb foo := a ; 'sta foo'
Code: Select all
; ca65 .define macro:
.define baz a
mb baz := bar ; will output 'lda bar'
mb foo := baz ; 'sta foo'
You might be able to:
Code: Select all
.define offset x
ldx index
lda table, offset