6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Sep 22, 2024 1:19 pm

All times are UTC




Post new topic Reply to topic  [ 31 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: Wed Aug 19, 2020 1:30 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
BillG wrote:
If you cannot tell, I am still trying to justify making an identity table an included feature in FLEX. Every time I think I need it, I find a way around it.

My instinctive reading of this is, "I am trying to find a reason to give the user 256 less bytes of free RAM. :-/

Maybe I'm missing something, but it feels like something that would never be useful enough to permanently embed in general-purpose code, but instead something you'd build only in those situations where it's showing a definite advantage. This might be because you've got free space in ROM on a particular system, as Garth points out, or something an application would build, possibly more than once during the run, as needed. If you have to reserve space for disk buffers for example, or need a GCR decoding table, you might use a buffer page or that table space for an on-the-fly identity table that you rebuild after disk I/O.

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


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 2:38 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 702
Location: North Tejas
cjs wrote:
BillG wrote:
If you cannot tell, I am still trying to justify making an identity table an included feature in FLEX. Every time I think I need it, I find a way around it.

My instinctive reading of this is, "I am trying to find a reason to give the user 256 less bytes of free RAM. :-/


That is the feeling I get too. It is a case of "if it was already there, I would use it, but I will not choose to make the sacrifice."

That is the motivation to ask those who have written more 6502 code than me...


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 6:51 am 
Offline
User avatar

Joined: Wed Feb 14, 2018 2:33 pm
Posts: 1467
Location: Scotland
BillG wrote:
cjs wrote:
BillG wrote:
If you cannot tell, I am still trying to justify making an identity table an included feature in FLEX. Every time I think I need it, I find a way around it.

My instinctive reading of this is, "I am trying to find a reason to give the user 256 less bytes of free RAM. :-/


That is the feeling I get too. It is a case of "if it was already there, I would use it, but I will not choose to make the sacrifice."

That is the motivation to ask those who have written more 6502 code than me...



Nothing to do with FLEX, but just a thought in-general. Way back when the BBC Micro was launched a criticism at the time was that it only had 32KB of RAM. This was in 1981 when the Apple II had 48KB (really 64KB by then). Both used RAM for video - the Beeb needs a whopping 20KB for "mode 0" which is a high resolution 640x256x1 display.

Digging deeper, or just got worse. The bottom 15 pages (3840 bytes) of RAM is used by the operating system and BASIC. Nearly 4KB! That's on-top of the 16KB BASIC ROM and the remaining 16KB being used by the OS ROM and IO space. Add a filing system ROM and that took up more lower RAM (ROMs are allowed to claim low-RAM, it's designed into the OS) So the more ROMs (mostly filing system/network ROMs) you added the less RAM you had for BASIC, word processing, etc.

But once we got over the seemingly lack of RAM we just got on with it. I wrote (and sold) programs for it, used Beebs to develop the basis of a flexible manufacturing system using their networking capabilities and the boffins at Acorn HQ went on to develop the ARM processor using it, and it didn't stop Elite being developed either.

Today, RAM is cheap, so when I started my Ruby project I stuck 64KB of RAM in it and didn't even think about trying to optimise my code for size. I just coded freely without that constraint. My OS is about 10KB and mimics the Acorn one without the graphics or multiple ROM support or sound or printer or a few other things I've probably forgotten. But it does have a nice CLI with editing and history and verbose error messages and a nice interface to the filing system though... If I load up BBC Basic or EhBASIC (which both live from $8000 in my system), it has usable RAM from PAGE (lomem) = $0E00 through $7FFF. Is anyone really going to write a program to use all that RAM today? Unlikely...

It also has a Sweet-16 interpreter in it which I re-wrote to be position independent and much faster than WOZs one. I initially used it to write a memory allocator in, but subsequently removed that code. The Sweet-16 interpreter is still in the OS image though and I'll remove it, if I ever need to.

So I think I'm saying that worrying about 256 bytes right now isn't (shouldn't) be an issue. Put it in and if you use it, then woo-hoo. And if at some point in the future you really need the RAM and haven't used it (or only used it once or twice), then work out how to remove it, if you really need to. There may be a question of historical accuracy though. Is that a thing?

However, I've been looking at these (Identity tables) for some time, but haven't found a use for the extra pseudo functions it can give me - yet - but if I do, then "losing" 256 bytes? I don't think I'll notice it.

Cheers,

-Gordon

_________________
--
Gordon Henderson.
See my Ruby 6502 and 65816 SBC projects here: https://projects.drogon.net/ruby/


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 7:09 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
BillG wrote:
That is the feeling I get too. It is a case of "if it was already there, I would use it, but I will not choose to make the sacrifice."

Well, now that I think a bit more about it, perhaps another approach is to make the sacrifice small enough that it's near-harmless for those who do not need to use such things.

As I mentioned, a DOS often has various non-trivial amounts of memory devoted to working area for disk buffers, lookup tables for GCR and similar translation, and so on, that are not needed at all times. It's perfectly reasonable for an OS to make this memory available to application programs if you can figure out a way to deal with the limitations on the use of this memory, such as the OS needing it from time to time.

So what about an API that lets you ask the OS for the address of a particular table, such as an identity table, allowing the application to use it until it makes any other OS call. After that, the application would need to call the API function again to get the table address (since it might need to be regenerated, or moved to a new location). The OS could, when called, generate the table into whatever convenient page of RAM that it owns and is not using at the moment, or simply return the address of an existing table if one is already available.

I'm not sure how useful this would be, but it should at least cost almost nothing to applications that don't need this, and potentially reduce the costs of such tables for applications that do.

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


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 10:30 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10938
Location: England
I don't know what FLEX offers by way of libraries for applications, but if there is a library story, perhaps this is something which could live in a library: applications which need it link against the library, and include it. Maybe there's even a load-time linking story?


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 11:01 am 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
If I was writing code that used lots of sequences thay could be streamlined with an identity table then I'd consider using one but I suspect most code wouldn't use it enough to justify the size of the table or the few cycles it saves. A free zero page location is almost always available or can be reserved for the job.

_________________
Andrew Jacobs
6502 & PIC Stuff - http://www.obelisk.me.uk/
Cross-Platform 6502/65C02/65816 Macro Assembler - http://www.obelisk.me.uk/dev65/
Open Source Projects - https://github.com/andrew-jacobs


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 12:06 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 702
Location: North Tejas
cjs wrote:
BillG wrote:
That is the feeling I get too. It is a case of "if it was already there, I would use it, but I will not choose to make the sacrifice."


So what about an API that lets you ask the OS for the address of a particular table, such as an identity table, allowing the application to use it until it makes any other OS call. After that, the application would need to call the API function again to get the table address (since it might need to be regenerated, or moved to a new location). The OS could, when called, generate the table into whatever convenient page of RAM that it owns and is not using at the moment, or simply return the address of an existing table if one is already available.


I thought about ways to ask an OS for the address of the table. The problem is that in code like this
Code:
 0BD3 79 D000       [4/5] 00195          adc    Identity,Y

the address of the table is hard coded into the instruction. The only thing I can come up with is a pointer to the table in the zero page, but that eliminates the use of the X register with the table. That plus the fact that (Identity),Y is one cycle slower - might as well use a temporary variable instead.


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 12:09 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 702
Location: North Tejas
BitWise wrote:
If I was writing code that used lots of sequences thay could be streamlined with an identity table then I'd consider using one but I suspect most code wouldn't use it enough to justify the size of the table or the few cycles it saves. A free zero page location is almost always available or can be reserved for the job.


I am writing compilers (and an operating system) and thought there might be an advantage to making an identity table a standard feature.

The compilers already have to create and use temporary variables, so might as well do that some more...


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 19, 2020 8:40 pm 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 674
BillG wrote:
cjs wrote:
BillG wrote:
That is the feeling I get too. It is a case of "if it was already there, I would use it, but I will not choose to make the sacrifice."


So what about an API that lets you ask the OS for the address of a particular table, such as an identity table, allowing the application to use it until it makes any other OS call. After that, the application would need to call the API function again to get the table address (since it might need to be regenerated, or moved to a new location). The OS could, when called, generate the table into whatever convenient page of RAM that it owns and is not using at the moment, or simply return the address of an existing table if one is already available.


I thought about ways to ask an OS for the address of the table. The problem is that in code like this
Code:
 0BD3 79 D000       [4/5] 00195          adc    Identity,Y

the address of the table is hard coded into the instruction. The only thing I can come up with is a pointer to the table in the zero page, but that eliminates the use of the X register with the table. That plus the fact that (Identity),Y is one cycle slower - might as well use a temporary variable instead.


The .o65 file format has a link table, and is supported by the ca65 assembler, so you can do load-time static relinking of your address references instead of always having to indirect through pointers at runtime. OS-provided stuff is very likely to be at a static address throughout the runtime. Even if OS-provided optional dependencies are lazily loaded on first use, it'll still likely be static during the lifetime of all programs that use it, even if it's unloaded later.

_________________
WFDis Interactive 6502 Disassembler
AcheronVM: A Reconfigurable 16-bit Virtual CPU for the 6502 Microprocessor


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 20, 2020 3:20 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 727
Location: Tokyo, Japan
White Flame wrote:
OS-provided stuff is very likely to be at a static address throughout the runtime. Even if OS-provided optional dependencies are lazily loaded on first use, it'll still likely be static during the lifetime of all programs that use it, even if it's unloaded later.

Well, not with what I was proposing, since I was proposing to use buffer and table space that happened not to be used by the OS at the moment for holding a generated table. That could go away with any OS call, later to be regenerated, possibly in a different location.

But yeah, a lazy-load into application space (as opposed to temporarily "spare" OS space) would work if done before the run-time link/address patch-up.

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


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 20, 2020 2:43 pm 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 702
Location: North Tejas
FLEX does not have any provision to do any relocation or fixups at load time and I am not inclined to change that.


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 22, 2020 1:59 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 395
Location: Minnesota
At first glance is that while regeneration on the fly is certainly possible, if the whole point is to save cycles, then you'd have to use such a table quite a bit before you dismissed it to be worthwhile doing.

Another thought is, do you need to allocate 256 bytes to it? That would be maximally flexible, but what if you knew beforehand that you'd only use it with positive values (or unsigned ones less than 128)?


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 22, 2020 2:59 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 702
Location: North Tejas
teamtempest wrote:
Another thought is, do you need to allocate 256 bytes to it? That would be maximally flexible, but what if you knew beforehand that you'd only use it with positive values (or unsigned ones less than 128)?


All 256 values are possible in the code in the last post on the first page of this thread.


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 22, 2020 3:45 am 
Offline

Joined: Thu Mar 12, 2020 10:04 pm
Posts: 702
Location: North Tejas
Using an identity table:

Code:
                          00390 ; 00020     W := S + (W + W);
 0BB2 18              [2] 00391          clc
 0BB3 AD 1140         [4] 00392          lda    W_
 0BB6 6D 1140         [4] 00393          adc    W_
 0BB9 AA              [2] 00394          tax
 0BBA AD 1141         [4] 00395          lda    W_+1
 0BBD 6D 1141         [4] 00396          adc    W_+1
 0BC0 18              [2] 00397          clc
 0BC1 A8              [2] 00398          tay
 0BC2 8A              [2] 00399          txa
 0BC3 6D 113F         [4] 00400          adc    S_
 0BC6 AA              [2] 00401          tax
 0BC7 AD 113F         [4] 00402          lda    S_
 0BCA 09 7F           [2] 00403          ora    #$7F
 0BCC 30 02 (0BD0)  [2/3] 00404          bmi    2f
 0BCE A9 00           [2] 00405          lda    #0
 0BD0                     00406 2:
 0BD0 79 D000       [4/5] 00407          adc    Identity,Y
 0BD3 8E 1140         [4] 00408          stx    W_
 0BD6 8D 1141         [4] 00409          sta    W_+1


Using a temporary variable:

Code:
                          00410 ; 00020     W := S + (W + W);
 0BD9 18              [2] 00411          clc
 0BDA AD 1140         [4] 00412          lda    W_
 0BDD 6D 1140         [4] 00413          adc    W_
 0BE0 AA              [2] 00414          tax
 0BE1 AD 1141         [4] 00415          lda    W_+1
 0BE4 6D 1141         [4] 00416          adc    W_+1
 0BE7 18              [2] 00417          clc
 0BE8 85 22           [3] 00418          sta    Byt0
 0BEA 8A              [2] 00419          txa
 0BEB 6D 113F         [4] 00420          adc    S_
 0BEE AA              [2] 00421          tax
 0BEF AD 113F         [4] 00422          lda    S_
 0BF2 09 7F           [2] 00423          ora    #$7F
 0BF4 30 02 (0BF8)  [2/3] 00424          bmi    2f
 0BF6 A9 00           [2] 00425          lda    #0
 0BF8                     00426 2:
 0BF8 65 22           [3] 00427          adc    Byt0
 0BFA 8E 1140         [4] 00428          stx    W_
 0BFD 8D 1141         [4] 00429          sta    W_+1


Using neither. This is one byte bigger and one or three cycles slower:

Code:
                          00430 ; 00020     W := S + (W + W);
 0C00 18              [2] 00431          clc
 0C01 AD 1140         [4] 00432          lda    W_
 0C04 6D 1140         [4] 00433          adc    W_
 0C07 AA              [2] 00434          tax
 0C08 AD 1141         [4] 00435          lda    W_+1
 0C0B 6D 1141         [4] 00436          adc    W_+1
 0C0E 18              [2] 00437          clc
 0C0F A8              [2] 00438          tay
 0C10 8A              [2] 00439          txa
 0C11 6D 113F         [4] 00440          adc    S_
 0C14 AA              [2] 00441          tax
 0C15 98              [2] 00442          tya
 0C16 2C 113F         [4] 00443          bit    S_
 0C19 10 05 (0C20)  [2/3] 00444          bpl    2f
 0C1B 69 FF           [2] 00445          adc    #$FF
 0C1D 4C 0C22         [3] 00446          jmp    3f
 0C20                     00447 2:
 0C20 69 00           [2] 00448          adc    #0
 0C22                     00449 3:
 0C22 8E 1140         [4] 00450          stx    W_
 0C25 8D 1141         [4] 00451          sta    W_+1


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 22, 2020 4:50 am 
Offline

Joined: Mon Sep 17, 2018 2:39 am
Posts: 136
Hi!

I never have found the use of an identity table useful, IMHO it is an example of a premature optimization - normally it is much better to optimize the overall algorithm than try to optimize individual instructions.

BillG wrote:
Using an identity table:

Code:
                          00390 ; 00020     W := S + (W + W);
 0BB2 18              [2] 00391          clc
 0BB3 AD 1140         [4] 00392          lda    W_
 0BB6 6D 1140         [4] 00393          adc    W_
 0BB9 AA              [2] 00394          tax
 0BBA AD 1141         [4] 00395          lda    W_+1
 0BBD 6D 1141         [4] 00396          adc    W_+1
 0BC0 18              [2] 00397          clc
 0BC1 A8              [2] 00398          tay
 0BC2 8A              [2] 00399          txa
 0BC3 6D 113F         [4] 00400          adc    S_
 0BC6 AA              [2] 00401          tax
 0BC7 AD 113F         [4] 00402          lda    S_
 0BCA 09 7F           [2] 00403          ora    #$7F
 0BCC 30 02 (0BD0)  [2/3] 00404          bmi    2f
 0BCE A9 00           [2] 00405          lda    #0
 0BD0                     00406 2:
 0BD0 79 D000       [4/5] 00407          adc    Identity,Y
 0BD3 8E 1140         [4] 00408          stx    W_
 0BD6 8D 1141         [4] 00409          sta    W_+1



This is smaller and faster, without using any temporary:
Code:
        lda     W_      ; 4
        asl             ; 2
        tax             ; 2
        lda     W_+1    ; 4
        rol             ; 2
        tay             ; 2

        txa             ; 2
        clc             ; 2
        adc     S_      ; 4
        sta     W_      ; 4

        bit     S_      ; 4
        bpl     l2      ; 2  3

        dey             ; 2  -
l2:
        bcc      l3     ; 2  3
        iny             ; 2  -
l3:
        sty     W_+1    ; 4   


Last three instructions could avoid the branch, but use one more cycle on the carry=1 cases:
Code:
        tya             ; 2
        adc     #0      ; 2
        sta     W_+1    ; 4


Have Fun!


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

All times are UTC


Who is online

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