6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Tue May 14, 2024 2:33 am

All times are UTC




Post new topic Reply to topic  [ 9 posts ] 
Author Message
 Post subject: IO opcodes
PostPosted: Sun Mar 04, 2018 5:00 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
I am planning to include optional IO opcodes in place of undefined opcodes of the 65C02 to enhance IO speed of my 65(C)02 emulator. The first obvious enhancement is that all IO addresses are on the same page. So only a one byte IO address is needed like in the zero page addressing mode. Furthermore a typical sequence for IO is LDA #, STA some_IO, which I could replace with a single opcode and 2 parameter bytes. It really takes off when a single opcode can transfer multiple bytes between memory and an IO address replacing a whole loop like LDA STA INX CPX BNE even without changing any register.

Let me know what you think of the idea. Below is an early draft of the opcodes. They would be implemented as macros and could be used with any assembler.
Attachment:
IO_opcodes.png
IO_opcodes.png [ 64.2 KiB | Viewed 4764 times ]
I will probably also implement the memory opcodes with indirect addressing.

Edit: update with more SD-card support

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
 Post subject: Re: IO opcodes
PostPosted: Wed Mar 07, 2018 12:28 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 672
I think that the "count" parameter has less use as an immediate byte, and makes much more sense to load it from a register, as buffers & packets are often dynamically sized. For instance, if you receive a message that starts with a length byte,
Code:
IN_A port
IN_C port, buffer
could pull in a dynamically sized packet, assuming IN_C used the accumulator to hold the count of bytes. The same is true for outputting a calculated-size buffer as well. Of course, you could simply add another IN & OUT instruction pair instead of replacing the immediate count versions.

Is there a reason you chose absolute addresses for base IO, while using indirect addresses for SD card transfers?

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


Top
 Profile  
Reply with quote  
 Post subject: Re: IO opcodes
PostPosted: Wed Mar 07, 2018 10:00 am 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
White Flame wrote:
I think that the "count" parameter has less use as an immediate byte, and makes much more sense to load it from a register, as buffers & packets are often dynamically sized. For instance, if you receive a message that starts with a length byte,
Code:
IN_A port
IN_C port, buffer
could pull in a dynamically sized packet, assuming IN_C used the accumulator to hold the count of bytes. The same is true for outputting a calculated-size buffer as well. Of course, you could simply add another IN & OUT instruction pair instead of replacing the immediate count versions.
Good idea! I could still use fixed size packets by simply preceding the opcode with LDA #. This makes the sequence 1 byte longer but so much more flexible.

I must admit that I focused too much on what I would need to drive an SD card but later developed the SD card specific opcodes to take care of that. An SD card has mostly fixed size command and response blocks.

White Flame wrote:
Is there a reason you chose absolute addresses for base IO, while using indirect addresses for SD card transfers?
I will probably implement indirect addressing on the general IO as well. For an SD card the need is clear as you need to read or write clusters of sectors to/from a continuous buffer. For FAT or directory access one would still work with a fixed sector buffer.

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
 Post subject: Re: IO opcodes
PostPosted: Wed Mar 07, 2018 9:23 pm 
Offline

Joined: Sat Dec 13, 2003 3:37 pm
Posts: 1004
Why do this?

I mean, now you're making a 65X02.

It's fair to argue that your code isn't going to be portable to some other system "anyway", so what difference does it make. You can macro wrap everything. But, the I/O instructions are kind of going against the flavor of the CPU family.

On my simulator, I have this:
Code:
   static final int CHAR_READY = 0xc000;
    static final int CHAR_DATA_IN = 0xc001;
    static final int CHAR_DATA_OUT = 0xc002;
    static final int DISK_SECTOR_LOW = 0xc003;
    static final int DISK_SECTOR_HIGH = 0xc004;
    static final int DISK_SECTOR_COUNT = 0xc005;
    static final int DISK_OP_ADDR_LOW = 0xc006;
    static final int DISK_OP_ADDR_HIGH = 0xc007;
    static final int DISK_OP_RESULT = 0xc008;
    static final int DISK_MODE = 0xc009;
    static final int DISK_CTL = 0xc00a;
    static final int SECTOR_SIZE = 256;

CHAR_READY has a 1 when a character is available from the keyboard, you can then read it from CHAR_DATA_IN. If you write to CHAR_DATA_OUT, it shows up on the screen.

Similarly, you populate the DISK_SECTOR count and the 16b DISK_SECTOR that you want, and the address. set DISK_MODE to read or write and then store a 1 to DISK_CTL, and "magic happens". DMA, yea, that's the ticket, a DMA Disk controller. High tech. So, it supports a single "disk" with 65K 256 byte sectors, 16MB. And you can read/write up to 256 sectors at a time.

More than enough for the FIG-Forth I was playing with at the time.

The simulator looks for read/write activity at those addresses and Does The Right Thing.

It's not as far as simulation of a VIA chip or a UART, but it does offer a wee taste of the whole memory mapped I/O experience, and doesn't need a new assembler or a bunch of macros.


Top
 Profile  
Reply with quote  
 Post subject: Re: IO opcodes
PostPosted: Thu Mar 08, 2018 12:57 am 
Offline

Joined: Tue Jul 24, 2012 2:27 am
Posts: 672
Another question that arises: What do you do when an interrupt triggers in the middle of a block transfer? Do you push state to the stack, and set a bit in the pushed processor status register on which RTI would resume it? (can't save it internally, due to potentially nested interrupts) Or simply wait until the instruction has completed?

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


Top
 Profile  
Reply with quote  
 Post subject: Re: IO opcodes
PostPosted: Thu Mar 08, 2018 11:37 am 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
In the early stages of my emulator I established a mechanism to retry incomplete IO instructions. An internal retry flag forces the RTI to set the PC to the current instruction instead of the next instruction. Therefore it is possible to interrupt an ongoing IO instruction after every byte. The retried IO instruction will continue with its internal pointers instead of reloading the original parameters. The retry flag is automatically cleared at the end of a retryable IO instruction.

I have to check my code, whether I catered for nested interrupts or whether I simply blocked CLI & NMI until RTI. I should probably implement a shadow stack for the retry flag.

I have added the current list of IO opcodes. It is a PDF now since it has grown beyond the size of my screen.


Attachments:
IO opcodes.pdf [357.23 KiB]
Downloaded 208 times

_________________
6502 sources on GitHub: https://github.com/Klaus2m5
Top
 Profile  
Reply with quote  
 Post subject: Re: IO opcodes
PostPosted: Thu Mar 08, 2018 12:37 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
whartung wrote:
Why do this?

I mean, now you're making a 65X02.

It's fair to argue that your code isn't going to be portable to some other system "anyway", so what difference does it make. You can macro wrap everything. But, the I/O instructions are kind of going against the flavor of the CPU family.
Which IO code would be portable without IO drivers? The macros to use the extra opcodes could be replaced with native 6502 code to make it portable. I plan to have an IO register to enable the IO opcodes. While the extra opcodes are not enabled all opcodes remain fully compatible.

There is already some DMA code in my emulator but more general than yours. While I was looking into expanding the DMA code to implement some SD card specifics I did some calculations on IO speed. As long as you just communicate with lower speed IO like a serial EEPROM or an USART channel it doesn't make a big difference, whether I do the IO with the emulator or the host of the emulator.

When it comes to SPI devices that run with the ATMega32's maximum speed of 8MHz it makes quite a difference to fetch most parameters of the IO from the instruction stream versus storing them to some IO address to setup your DMA. It is the .5µs memory read versus doing a LDA STA INX BNE loop of the emulated machine which consumes at least 5µs instead. Of course once DMA is going there is no more difference. However, on an SD card there is also the need to program loops to wait for a token or for the end of busy because you need to react to the token or possible error code. An additional benefit are the simple IO opcodes being 1 or 2 bytes shorter and the emulator does not need to look at the address in order to decide whether they are IO addresses or not.

Later I may look into implementing more specific DMA features anyway. Currently I think I like the convenience of the extra opcodes over fiddling with DMA control blocks.

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
 Post subject: Re: IO opcodes
PostPosted: Thu Mar 08, 2018 1:34 pm 
Offline
User avatar

Joined: Tue Mar 02, 2004 8:55 am
Posts: 996
Location: Berkshire, UK
I use pseudo instructions for I/O in my em-retro emulators. I try to have a minimal set of opcodes and pass data in registers (normally the accumulator). I don't have any bulk operations so I'm not out the cycle stepping loop for long periods of time. The details are in the README.md at the bottom of this page.

https://github.com/andrew-jacobs/em-retro

_________________
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  
 Post subject: Re: IO opcodes
PostPosted: Thu Mar 08, 2018 3:53 pm 
Offline

Joined: Sat Jul 28, 2012 11:41 am
Posts: 442
Location: Wiesbaden, Germany
BitWise wrote:
I use pseudo instructions for I/O in my em-retro emulators. I try to have a minimal set of opcodes and pass data in registers (normally the accumulator).
So you use COP nn as the escape code to address an IO register much similar to my IN_A and OUTA except that I have separate opcodes for read and write.

BitWise wrote:
I don't have any bulk operations so I'm not out the cycle stepping loop for long periods of time.
My bulk operations may use up a lot of cycles but are interruptible and should not cause delays to interrupt handling longer than other native 6502 opcodes. Of course there are some obvious limitations. Time critical work must be interrupt driven. The bulk device itself should not cause any interrupt and during a running bulk operation one cannot start any other bulk operation.

_________________
6502 sources on GitHub: https://github.com/Klaus2m5


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 9 posts ] 

All times are UTC


Who is online

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