This is something I posted in reply to a thread about implementing 6809 in programmable logic in the Motorola 6809/6309, 6800 Assembly Language Programming group on Facebook.
The original post kind of asked about features one might think useful to add to the 6809.
I immediately thought of my daydreams about CPUs. But I didn't have time to reply.
(The post in the above group mentions the "secret" extensions in the Hitachi 6309, which was first described in detail in an article in Oh! FM, and a usenet post by Hirutsugu Kakugawa, which you can find linked in my post of my translation of the article from some years back. I posted some of my own incomplete and somewhat incoherent thoughts on extending the 6809 some time back, which might be of useful reference, or might not.)
I woke up in the middle of the night to shut my computer off, and stopped and wrote a reply. That reply follows, augmented to make it a little more coherent (maybe):
One of the reasons I am not a fan of the 6309 is that it is kind of a random set of extensions that pushes it into the 16-bit world haphazardly. It ends up a 16-bit CPU on an 8-bit data bus with only a 16-bit address bus, and an odd set of features.
(You can get a look look at the extensions in my translation of the Oh! FM articles. I have never posted a proper critique of the 6309's extensions. Others have, however.)
One of the ways that the 6809 really needs extending is the size of the address space. The 6809's instruction set is powerful, but 64K is a tight squeeze for advanced operating systems to co-exist with application code in. OS-9/6809 shows that a lot can be done, but there are limits. I think the address space limits are no small part of the reason we never got a C89 compiler for OS-9/6809, and why OS-9/6809 did not find greater acceptance as a desktop/workstation operating system.
OS-9/6809 expands the address space by bank switching. This works will enough to allow multiple applications to be running at once, but it does so by giving the 6809 multiple 64K-max address spaces. If you need to reference objects that approach 64K in size, you end up without a lot of code in the same address space.
You have to go through the bank switches to create virtual address spaces larger than 64K, and those virtual address spaces are time consuming at run-time. So bank switching is available with the existing 6809 (and 6309), but it's not an ideal solution.
You can go one of two directions in expanding the 6809's address space without using bank switching..
One would be to add segment registers. That's what Intel did with the 8086.
Another would be to widen the existing address registers and keeping linear addressing. This was done by Interdata and Prime with their minicomputers in the early 1970s, and by Intel with the 80386 and Zilog with the ez80 and Z380 from mid-1980s and beyond.
I tend to prefer the latter approach, so that you can separate memory management from addressing. But it may not provide seamless upgrade for existing code, when address math suddenly has more room before it overflows.
It is one of the flaws in the 8086 that memory management gets mixed with addressing -- and then they offset the stupid segment registers by 4 bits instead of 8, which makes address calculation about, oh, 3 to 5 times as time consuming (more than twice, less than eight times).
And that is probably a rather opaque complaint.
Segmentation allows you to provide multiple address spaces, like bank-switching, but the individual address spaces are linear with segments, where bank switching allows you to have non-linear address spaces.
What that means is that, with bank-switching, you can put a bunch of shared code in a range of addresses into a group of address spaces. Or you can put a shared data structure in multiple address spaces, switching code in and out around it. You can't do that with segmentation.
On the other hand, with segmentation, address calculations when you need to reach beyond the natural address space (the 64K space defined by 16-bit address registers) are less cumbersome. And you don't need the extra step of switching banks.
But address calculations when segmentation is in the way does require extra math.
With the 8086, 16-bit segment base registers are offset 4-bits from the addresses in the index registers. That means you have to shift the segment register contents by 4 bits (multiplying by 16) and use a 24-bit or 32-bit addition to add the segment to the index register contents. That's more than twice the number of instructions than address math that stays within the 64K address space.
If we want to do segment registers, we either don't want to shift the segment base registers, meaning that the segment base registers either have to be the full physical width, 24 or 32 bits, and that segment bases have to be handled in pieces, or that segment base registers should be shifted right a full byte to simplify the math, meaning that you probably want 16-bit segment registers, for a physical width of 24 bits.
(24 bit segment registers could be interesting, for a physical width of 40 bits, but boot time memory checks in 16 Megabytes is going to take a long time on an 8-bit CPU. Terabyte is meaningless unless you are trying to use the extreme address width to isolate stacks and heaps and code from each other or some such thing.)
Widening the address registers to keep linear addressing simplifies the math, and it means that you don't need to play games to keep all the code and data you want to access, if it all fits in the same 16 megabyte (24-bit addresses) or 4 gigabyte (32-bit addresses) address space.
If you want to limit what is accessible in various address spaces with the widened address registers, you need memory management hardware, which looks a little like segmentation, but is not.
But you can sort-of use segmentation to implement such limits on the 8086. But you can do math on the segment numbers and there is no enforcement mechanism. You can pretend the limits are there, but they can't be enforced.
The 4-bit shift does mean that pointers can be made obfuscated, but obfuscation protects only from well-behaved applications and users.
On the 80286, they can be enforced, but then you run into problems when you want to access those large data objects and a lot of code. You have to use a lot of code, much like with bank-switching.
And that is why I say segmentation mixes addressing with memory management.
Now, back to what can happen when you widen the address registers and keep the addresses linear, let's look at an example.
Say you have code that is supposed to run on the 6809. It is loaded around address 32,000 (decimal) and branches forward 3,000 bytes. On the 6809, the address 35,000 is where you jump to.
If you have extended the addressing with segmentation, that's not a problem. Your segment register for the PC is zero, and it stays zero, and the PC has 35,000 in it, and that is that.
If you have widened the PC linearly, yes, the address in the PC may be 35,000, but if the code is a ROM stored 29,000 from the end of memory (which is where it was in the 64K address space of the 6809), the code you're expecting at address 35,000 is not there. If the PC is now 24 bits wide, the code is at address 16,748,216. If the PC is now 32 bits, the code is at address 4,294,938,296.
Which means that you need to make sure your ROMs are placed where they need to be in the expanded address space. This may place design limits on the updated versions of the computers you are planning to put the extended descendant of the 6809 in.
You have to be more careful when you extend the address register widths linearly.
Either way, linear or segmented, the PC, S, U, X, Y, and DP get extra bits.
Also, the extended addressing (in other words, absolute) mode should get extra bits. That means a segment register-like register for extended mode addressing.
Kind of like the direct page register, you may be thinking? Yeah. Kind of a lot like the direct page register.
Speaking of the direct page register, it also gets extra bits or a segment register.
Or does it?
The direct page register is actually a segment register, if you think about it.
For the purposes of the direct page register, it might be reasonable to limit it to the first 64K of address space, in which case the DP would not be widened.
And, really, extended address mode might be left as is, assuming that everything you want to access with absolute addresses will be in the lowest 64K of memory.
Or you could add op-codes to add an extended-extended mode to access absolute address greater than 64K, leaving the original extended mode to address into the lowest 64K only, but that just feels wrong.
Or extended mode could be considered signed, in which case it would access from address 4,294,934,528 to address 32,767 if widening addresses to 32 bits (16,744,448 to 32,767 if 24 bits). (That's from 215 below the maximum address to 215-1 above zero, in other words, -32,768 to +32,767.)
If doing segment registers in the 6809, do NOT give U and S the same segment register. Saving transistors by giving BP and SP the same segment register was another huge flaw in the 8086. It keeps us from using the BP as a parameter stack pointer completely independent from the return address stack pointer, which is the way parameters should be done.
On the 6309, there is another register that can be used as an index, I think it was called W in most of the (purported) reverse-engineering documentation. That register also needs extra bits when you expand the address space of the 6309.
Since W is also the high 16 bits of the 32-bit accumulator, widening it is going to have odd consequences. Likewise, giving it a segment register is going to mean that it often points to stuff that is not stuff that you intend to point to, since it is the upper 32 bits of certain operations.
Since we are somewhat used to using X for intermediate integer results on the 68HC11, it feels like the latter option is less of a problem than the former, which pushes the 6309 towards segmentation rather than address widening.
How many extra bits we should give addresses depends on whether you want to keep the expanded CPU in an expanded 8-bit calculation space or push it into a 16-bit calculation space, or even into a 32-bit calculation space.
Eight extra bits wider gives it enough more address space, even as an 8-bit CPU, to implement UNIX 7 (AT&T) or UNIX system 5 (BSD). That can target true 16-bit applications, and even early Macintosh/Amiga/GEM/etc. level graphical user interfaces.
(You will note that OS-9/6809 has Multi-Vue/Mshell, and it works rather well, even compared to early Macintosh. And I will agree. Again, the problem is squeezing the extra application stuff in with the OS. Small applications work great. Larger data/code gets frustrating and prone to addressing-related bottlenecks. Thus, we want at least 24 bits of addressing.)
16 extra bits wider pushes it more towards the 32-bit calculation space required for Linux OSses to run comfortably. If you think you want to make a step to a smooth upgrade path to 32-bit calculation space, you probably want to go ahead and expand the address space by 16 bits, not 8. And that pushes us in the direction of linear addressing.
Also, the 16-bit jump will be a smoother step to the 64-bit calculation space, if you want to look that far ahead. Think the difference in direction between the 80286 and the ix386 architectures.
If you want your processor extensions to be competitive with the 8086, and are content to remain in the 8-bit calculation world, 16-bit segment registers offset by 8 bits to give 24 bits of address space would be sufficient, and would retain a greater level of compatibility with existing applications -- but be careful how you handle the interrupt vector space.
Oh, you might even want to give interrupt vector space its own segment, separate from the extended address mode space. Or you may not.
Anyway, expanding the address space is something I strongly recommend if you are extending the 6809 or 6309.
On a related note, one of the failings of the 6309 was that they didn't give the DP-based modes their own presence in the index post-byte, although that is partially, if clumsily, addressed by the providing the W register as sort of some-times alternative page base register.
I started writing this around 2:30 AM, which is part of the reason it was somewhat incoherent. Part of the reason.
Now, that is the essence of what I posted to the FB group, with perhaps enough explanation to make it somewhat coherent.
So I want to talk about the DP.
Widening DP and keeping it at an 8-bit offset would be a reasonable interpretation of DP as the heap segment base.
It needs to be in the indexed addressing modes, so that you can use LEA instructions to take the address of variables in the DP, and so that you can indirect through indexes stored in the DP without pulling them into the CPU.
Keeping DP in the bottom 64K could make sense, especially if the CPU has on-chip RAM in those areas. It would, however, mean that DP could not be the base of the heap, since a process's heap wants to be out, away from stuff that will be allocated to other things.
And if we put DP mode in the index mode post-byte, you could have both 8-bit and 16-bit offset modes, making the DP even more useful as a heap segment base.
Since the OS wants a DP-like register to point to banks of hardware interfaces, I would want another DP-like register. That may have been part of the reason the architects of the 6309 extensions put the W register in the index mode post-byte.
I wrote on a related subject, de-generalized caching, for the 6801, here:
And for the 6809, here:
Speaking of the 6801, if we were considering widening the address space of the 68HC11, I would definitely go with segmentation. The 6801 and 68HC11 are basically 8-bit CPUs with 16-bit accumulators that can be split.
But since you've only got one X in the 6801, it's going to be a lot of shuffling segment bases around in large-model applications. So maybe not for an extension to the 6801. Maybe for an extension to the 68HC11, or an extension to the 6801 that has SBX to parallel ABX, and DP versions of the unary operators, and adds the 'HC11 extensions in different places in the op-code map. And a U stack pointer for the parameter stack.
The DP for such an extension of the HC11 might split the direct page into four 64-byte regions with an offset register to move each block of 64 bytes of address up higher, which would allow fast process switching for code that uses DP as pseudo-registers.
No comments:
Post a Comment