Joined: Fri Aug 30, 2002 1:09 am Posts: 8438 Location: Southern California
|
Thanks Mike for pointing out Andre Fachat's work. He has done an impressive job of devising an operating system that can handle multiple programs in memory at the same time. I definitely should take time to look at it in more detail.
There is one thing I did not see at the website, although Mr. Fachat may be doing it—that is, addressing the possibility of truly relocatable 6502 code, such that the program does not need extra tables (except for other programs to use parts of it) or any special considerations at load time. It's not efficient, but handling long relative addresses can in fact be done on a 6502 because the JSR instruction puts its own last byte's address on the stack. This means that regardless of where the program got loaded, the run-time address of a given part can be known and used for adding an offset to it, getting addresses for data or long branching even though the absolute address information was not known at the time of assembly and the code was not modified at the time of loading.
The JSR itself does not use a relative address, so that address can't move around; but the same routines that calculate addresses at run time could be used by several programs that got loaded into memory in any order. This may be part of Mr. Fachat's OS—I don't know. As you can see, the JSR will not always be used for the usual calling of a subroutine—in fact, you might use RTS to do a call or a jump, after the calculated address (minus one) is put on the stack.
I have toyed with this idea some, but I cannot say I've been using it. And while I have used the 65816 some, the attractions I have taken advantage of are primarily the added ease of handling 16-bit numbers and many of the new instructions and addressing modes. I have not specifically taken advantage of its resources for facilitating relocatable programs or for using a 16MB address space.
Quote: Garth, I have a question since I have no 65816 experience, but am looking forward to working with one. Can 65816 code be relocated arbitrarily or only on 64K boundaries? Are there relative JMP and JSR instructions? With that said, schidester, understand that my information comes from the WDC programming manual, and that some of the extra instructions I mention are ones that I have only used for reasons other than writing relocatable code.
So we have (and this is definitely not an exhaustive list):
- PEA: push 16-bit immediate data onto stack (without affecting processor registers)
- PEI: like a 16-bit LDA from direct page, then PHA, but without affecting processor registers
- PER: Add the current (run-time) program counter value to the 16-bit signed displacement in the operand, and push the result on the stack. The program counter value used is the one effective at run time, and could be different every time the program is loaded.
- BRL: branch relative always long
There is no BSR (branch to subroutine) or JSR-relative-long instruction, but it can be easily synthesized just by using PER return-address-minus-one, BRL (branch relative long). In this case you actually have the advantage that you can specify the return address relative to the calling address, and you don't necessarily have to return to the very next byte or instruction. An example of its usefulness would be where the next several bytes are data to be used by the subroutine. When the subroutine is done, you don't want the program counter to come back and start trying to execute bytes that are data and not instructions. I've done this kind of thing with the 65c02, but the 65816's new instructions would have made it much easier and far more efficient.
For another example, consider the situation where you want to pass several parameters to a subroutine via the stack (good for re-entrancy or recursion), and have it return with the stack already cleaned up. To make the clean-up easier, you can use PER to first push the return address, then use PER or PEA (in addition to the usual PHA etc.) to push parameters or their relative addresses onto the stack, and then do the actual subroutine call with a BRL.
There is also a JSR(addr,X), ie, absolute indexed indirect. Remember X can be 16-bit.
If you push an address onto the stack as a parameter to pass to another routine, you can use instructions like ADC (sr,S),Y (ie, stack-relative indirect, indexed by Y). In essence, you can tell it something like, "get the 5th and 6th bytes on the stack, read the address pointed to there, add Y (which may be 16 bits) to it, get the 8- or 16-bit data contained at the resulting address, and add it to the accumulator's contents." If you're doing a 16-bit operation, it takes 8 clocks. Otherwise it takes 7.
The stack-relative addressing modes make it easier to use the stack for parameter-passing. Especially with 65816's 16-bit stack pointer, you don't have to worry about running out of stack space.
To dispel some common misconceptions about the 65816 [Edit, 20 years later: I have a more complete article about that, here]:
- I sense that it intimidates a lot of 6502 fans; but the '816 is really not hard to get into. You can initially start using it virtually the same as a 6502, and begin taking advantage of its extra capabilities as you learn them.
- You don't always have to handle 16 bits at a time. The accumulator can be 8 or 16 bits, and for some purposes is viewed as two 8-bit accumulators. X and Y can be either 8- or 16-bit, although you cannot have X set to 8-bit and Y set to 16-bit (or vice-versa) at the same time. Whether A or X&Y are 8- or 16-bit can be changed on the fly as often as you like. My '816 Forth kernel leaves A at 16-bit and X & Y at 8-bit most of the time.
- You don't have to latch, decode, or use the high 8 bits of the 24-bit address bus. You can ignore it and just use the low 16 bits (resulting in a 64K address space) if you wish.
- Although the '816 has 256 banks of 64KB each, it still has 256-byte pages, along with the DP (direct page) addressing modes that make for two-byte instructions. DP is not called ZP, because it does not have to be in page zero. It can be anywhere in the low 64K address space. It doesn't even have to start on a page boundary. You can move it around on the fly too.
- The bank boundaries are not transparent in most respects, so to answer part of schidester's question, although the program can be moved around within a bank, you wouldn't want to have it straddle a bank boundary if it wasn't written to do that. The data bank and program bank registers allow you to operate in various banks without the inefficiency that would be presented if you always had to use 24-bit addresses; but you can still access any part of the 16MB address space by using long addressing modes (with 24-bit addresses) which ignore the bank registers.
_________________ http://WilsonMinesCo.com/ lots of 6502 resources The "second front page" is http://wilsonminesco.com/links.html . What's an additional VIA among friends, anyhow?
|
|