Page 1 of 3

Instruction use frequency?

Posted: Sun May 17, 2015 5:11 am
by yzoer
Hi all!

Does anyone know if there's some sort of analysis on instruction frequency for the 6502? Particularly interested in indirect,x and perhaps a lot more common (just curious though) about cpx / cpy.

Thanks!

Yvo

Re: Instruction use frequency?

Posted: Sun May 17, 2015 7:46 am
by BigEd
It's an interesting question. There's a small table at
http://www.slack.net/~ant/nes-emu/6502.html#frequent
[Edit: may be offline, so see archived version here.]

Shouldn't be too hard to tweak an emulator to produce these stats for a given program - I'm sure I've intended to do it, but I can't find a record of any results, so I'm pretty sure I never did it.

(For some purposes, dynamic frequency is what you want (so instructions inside loops are counted many times) but for other purposes static frequency might be more useful, or as useful (so you can just count the output of an assembly listing or disassembly listing.))

Re: Instruction use frequency?

Posted: Sun May 17, 2015 8:40 am
by GARTHWILSON
It will also depend on the language and what you're doing with it.

Re: Instruction use frequency?

Posted: Sun May 17, 2015 9:06 am
by theGSman
yzoer wrote:
Particularly interested in indirect,x
I have never ever used that mode nor have I seen it in anybody else's code. In fact, I can't think of a practical application for it.

Re: Instruction use frequency?

Posted: Sun May 17, 2015 9:38 am
by White Flame
While instruction popularity is very usage specific, I'd say that ROM-based systems like the NES (used in the link above) would weight heavily against STA, especially STA abs, as opposed to RAM-based programs and tables.

(Indirect,x) is only found in some programs, often interpreters or other higher-level tools that do a lot of dynamic memory management... and then not at all in the majority of other programs. However, its most common usage that I've seen is LDA(0,X), where .X is a pointer to a ZP stack, as in many Forth interpreters. It would dereference a byte whose address is held in the top of the stack. I've also used it in some sprite multiplexers, where X is a multiple of 2, shuffling around a table of pointers in zeropage. It's not super efficient, but is well organized and keeps the code pretty small.

cpx/cpy I'd consider to be pretty rare. While their obvious use would be in loops, often they're optimized out so that dex/dey, bne is used instead, which is less runtime overhead.

Re: Instruction use frequency?

Posted: Sun May 17, 2015 10:25 am
by scotws
As an aside, I'm curious why they used a really big CASE statement for the emulator. I'm throwing together some experiments for a possible 65816 emulator (because there doesn't seem to be a good one for Linux around), and I thought it would be obvious to use a jump table with the opcode value as the index.

Then again, I'm using Forth and he's using C, so maybe that's the difference?

Re: Instruction use frequency?

Posted: Sun May 17, 2015 11:20 am
by Tor
Jump table vs case statement may have to do with the instruction set. I wrote two emulators, both in C, one used case statements (because the instruction set kind of made sense for that), while the other used a jump table due to the emulated CPU's huge number of opcodes.

Re: Instruction use frequency?

Posted: Sun May 17, 2015 11:35 am
by BitWise
scotws wrote:
As an aside, I'm curious why they used a really big CASE statement for the emulator. I'm throwing together some experiments for a possible 65816 emulator (because there doesn't seem to be a good one for Linux around), and I thought it would be obvious to use a jump table with the opcode value as the index.
C compilers usually analyse the number of cases and optimise the dispatch mechanism. For a few cases they often generate the equivalent of nested if/then/else. For a large number you usually get a jump table.

Re: Instruction use frequency?

Posted: Sun May 17, 2015 7:25 pm
by BigDumbDinosaur
theGSman wrote:
yzoer wrote:
Particularly interested in indirect,x
I have never ever used that mode nor have I seen it in anybody else's code. In fact, I can't think of a practical application for it.
How about JMP (<addr>,X), which exists in the 65C02 and 65C816, and is conceptually like ON-GOTO in BASIC or SWITCH in C? I use JMP (<addr>,X) a lot.

The 65C816 also has JSR (<addr>,X).

Re: Instruction use frequency?

Posted: Sun May 17, 2015 9:16 pm
by barrym95838
If zero-page is already crowded, you can use (zp,x) to slide blocks up and down up to 255 bytes with a single vector, like in my VTL02 interpreter:

Code: Select all

        ...
        tay  		y = length of line to delete
        eor  #-1	
        sec  		
        adc  ampr	{&} = {&} - y
        sta  ampr	
        bcs  delt	
        dec  ampr+1	
delt    lda  at		
        sta  under	{_} = {@}
        lda  at+1	
        sta  under+1	
delt2   lda  under	
        cmp  ampr	delete the line
        lda  under+1	
        sbc  ampr+1	
        bcs  insrt	
        lda  (under),y	
        sta  (under,x)	
        inc  under	
        bne  delt2	
        inc  under+1	
        bcc  delt2	(always taken)
insrt   ...
(zp,x) is also used in fetch-type operations (FigForth's @):

Code: Select all

L773      .BYTE $81,$C0
          .WORD L762     ; link to TOGGLE
AT        .WORD *+2
          LDA (0,X)
          PHA
          INC 0,X
          BNE L781
          INC 1,X
L781      LDA (0,X)
          JMP PUT
Mike B.

Re: Instruction use frequency?

Posted: Mon May 18, 2015 2:51 am
by White Flame
scotws wrote:
As an aside, I'm curious why they used a really big CASE statement for the emulator. I'm throwing together some experiments for a possible 65816 emulator (because there doesn't seem to be a good one for Linux around), and I thought it would be obvious to use a jump table with the opcode value as the index.

Then again, I'm using Forth and he's using C, so maybe that's the difference?
In the article, he describes the reason: The C compiler will put all of the case bodies' variables in the same scope, reusing variable slots and potentially using CPU registers for many of them. I guess that is pretty Forth vs C specific.

Re: Instruction use frequency?

Posted: Mon May 18, 2015 3:59 am
by yzoer
Thanks for the input guys! Aside from indirect,x I was actually surprised that cpx/cpy wasn't really used that much. Personally, I haven't really used it that much and generally used them either as loop (down) counters or primarily as index registers.

-Yvo

Re: Instruction use frequency?

Posted: Mon May 18, 2015 6:56 am
by theGSman
White Flame wrote:
The C compiler will put all of the case bodies' variables in the same scope, reusing variable slots and potentially using CPU registers for many of them. I guess that is pretty Forth vs C specific.
A modern optimizing C compiler can generate more efficient code than even an assembly language programmer can produce. In this modern highly evolved information age, low level programming is going the way of valves and relay sets.

This is why nostalgia sites like 6502.org exist; so that members can experience computing and programming like it was in the pioneering days of the 80's.

Re: Instruction use frequency?

Posted: Mon May 18, 2015 1:08 pm
by BigEd
A quick and dirty disassembly of the BASIC and OS for Acorn's BBC micro, which are 16k each, show the following static frequencies:
OS:
,X) 89
cpx 67
cpy 38
bne 338

Basic:
,X) 69
cpx 72
cpy 51
bne 356

As expected, cpx and cpy are usually followed by a branch:
cpx:
10 bcc
24 bcs
31 bne
32 beq
cpy:
7 bcc
13 bcs
17 beq
31 bne

Re: Instruction use frequency?

Posted: Mon May 18, 2015 4:23 pm
by BigDumbDinosaur
theGSman wrote:
White Flame wrote:
The C compiler will put all of the case bodies' variables in the same scope, reusing variable slots and potentially using CPU registers for many of them. I guess that is pretty Forth vs C specific.
A modern optimizing C compiler can generate more efficient code than even an assembly language programmer can produce. In this modern highly evolved information age, low level programming is going the way of valves and relay sets.
Don't count out tubes (valves) and relays just yet. Tube amplification is quite popular with musicians and audiophiles. My company does contract work for another company that sells tube-powered guitar amplifiers.

As for relays, billions are produced and used every year. Railroad signalling is a big user of relays, which are generally more trustworthy than their electronic counterparts in the harsh operating conditions encountered in such service.

Regarding the output of a C compiler versus an expert assembly language programmer, I disagree. A human programmer can always do a better job of optimizing code than any automatic code generator—which description applies to a language compiler. The programmer can often see patterns that a compiler cannot, which means the programmer can use that information to develop a tighter and faster routine.

That said, modern MPUs (especially the x86 family) have gotten so complicated and opaque, it's generally not economical anymore to write in assembly language.
Quote:
This is why nostalgia sites like 6502.org exist; so that members can experience computing and programming like it was in the pioneering days of the 80's.
Dunno how old you are, but to me, the "pioneering days" were the 1950s and 1960s. :lol: