Open Bananattack opened 5 years ago
Keyword bike-shedding: Might go with ioreg
(short for "I/O register") rather than ioport
for the keyword. import
is very close in spelling (for readability), and might be easy to mix up with ioport
during reading if not looking carefully (writing it that way is another story, since they're syntactically different enough). Also ioreg
is shorter.
io
also looks nice as an even shorter qualifier, but making it a reserved keyword would clash with user-defined identifiers. Probably not possible to make it a contextual keyword without introducing ambiguity.
There could also be iospace
just to indicate that the address exists in I/O space without saying it's a "register" per-se, but it's even longer than the other suggestions.
Reading and writing to I/O ports on the Z80, is a bit cumbersome compared to writing to memory-mapped I/O registers right now, because you need to use instrinsics to access them:
For simple read/write, it would be nice if it were as convenient as writing to a memory-mapped register, where you can just use assignment style syntax. In other cases, where there are several operations going on, it might make sense to keep them as intrinsics.
The other issue is that when calling these I/O functions, they currently just take a u8, which is easy to mix up if you're not careful. For the time being, it has meant all I/O port related definitions for SMS/GG and MSX are declared in their own namespace to help prevent passing the wrong address. This sort of separation is kinda helpful because, as an example, it prevents mixing up VDP-side register addresses with the I/O ports used to access the VDP.
If the type system could enforce that only I/O addresses (or integers explicitly casted to them) are passed to the io functions, that would save a lot of small debugging headaches. Allowing a type would also allow a more convenient assignment syntax to be possible. And it would allow taking the address of I/O ports, and treating them as a distinct kind of pointers that is separate from regular pointers.
SDCC (a C compiler for Z80 systems) seems to have support for I/O port declarations. Some platforms that GCC supports have a way to mark something as an I/O port as well, via attributes. It could be pretty handy. Especially, as a part of type system, not just an attribute.
Another benefit of I/O ports being part of the type system, is that it would also interact with writeonly/const qualifiers, so you could have separate port declarations for a read-only and write-only view of the same port address. (This can be useful if you have a different set of flags that are read than can be written. eg. a port that is a command port on write-side, but status port on read-side)
I think we should add a new keyword
ioport
(orio
, or maybe something else, TBD).Then stuff like this would be possible:
and code like this would work (no calls to i/o functions needed here)
For the other I/O calls, they would remain the same, but would take I/O port arguments instead. This would also prevent passing a raw u8 to something that expects an I/O port, without casting to acknowledge you know what you're doing.
on Z80
sizeof(*ioport T)
would be 1, because I/O port indices are 8-bit. So I/O port pointers could be a different size than memory pointers potentially.The trickiest bit would probably be adjusting the platform system to handle other kinds of pointers. It supports far pointers, right now, but it probably needs a way to support yet another pointer type, with its own platform-specific size. And unlike far pointers (which are almost always useful, even if the CPU can't handle them, due to memory mappers / bankswitching being common on almost all 8-bit systems), I/O port pointers shouldn't need to exist on systems that lack a separate I/O bus since they'd actually have no use on a platform lacking that feature.
The other tricky part would be propagating the
ioport
qualifiers of variables and pointers.Maybe there will be other discovered work along the way. But this is a rough sketch of the idea that should give a general outline on how this feature could work.