6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 14, 2024 9:34 pm

All times are UTC




Post new topic Reply to topic  [ 30 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Fri Apr 20, 2012 8:58 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
My TBR is a bit like the 816's PBR in the sense that it can't be changed on a whim, or even dreamt of changing on a per-instruction basis, because it jumps the program flow to a completely different place. In that sense, I don't think it introduces the difficulty you mention, with having to remember which mode you're in. (I agree that it would if it applied only to data accesses.)

The T bit is much more like a supervisor mode, you're either intentionally and deliberately dealing with tasks and their resources, or you're within a task. Somewhat like the difference in mindset between programming an interrupt handler and programming regular code - you don't forget which one you're in, because one is a special case, and the minority case.

The T bit is also a bit like emulation versus native mode, in that one can just start the machine in T=0 mode and run all your code in task mode and never worry about TBR. It doesn't have to get in the way for anyone who isn't interested in multitasking or relocation.

Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 12:18 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 410
Location: Minnesota
Quote:
So if we added a JMP (address),Y mode we're all set, with minimal change. Although I think that needs quite some change, as it happens.


Mmm...trying to decide if I understand this. JMP (addr,X) I understand: jump to the address stored at memory locations X and X+1 beyond addr. So: add X to addr to get addr+X, then load the two consecutive bytes starting at addr+X into the program counter.

We can use that pre-indexed mode to set up a nice jump table from addr to addr+X.max-1. Okay.

But JMP (addr),Y? That's post-indexed, so...how would it work? As near as I can tell it would be: load one byte from addr, add the contents of the Y-register to it, then load a byte from addr+1, add the carry flag to it, and load the resultant two-byte value into the program counter. Yes? So: add Y to (addr) to get (addr)+Y, then jump to that address.

Okay...so you can jump anywhere from (addr) to (addr)+Y.max-1. Hmm. Possibly more useful if Y.max is 65535 rather than 255, although you can change addr itself to anywhere in memory.

Your idea is to set (addr) to zero, then use Y as an offset to the start of any routine within its range? Wouldn't that work for anywhere in memory the code might be loaded only if TBR held the physical base address for translation? But if that's the case, why not simply JMP addr, since TBR will take care of adding the necessary offset anyway?

Or is this instead of a TBR register? Or do I not understand what you're driving at?


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 12:43 am 
Offline

Joined: Sun Nov 08, 2009 1:56 am
Posts: 410
Location: Minnesota
Quote:
If there were also something like LDA(FOOBAR,X),Y, with the extra index registers, that would probably meet nearly everything needed for relocatable code and multitasking.


This is interesting. A table of data addresses pre-indexed by X (to get one particular data area) and then post-indexed by Y (to get one byte in one particular data area)? Does the OS fill in the table at load time?

My own thought would be to give more and more instructions a program-counter relative mode like the branch instructions have. A problem for branch-to-subroutine (BSR), much as I like it, is that its range is limited to what will fit in a single byte (at least if it keeps symmetry with the other branch instructions).

But if there was a way to give JMP or JSR a program-counter relative mode, there might not be any need for code address fixups at all. The OS could load a code block whereever it wanted - even relocate it if necessary - without having to fiddle with anything inside it.

Of course that wouldn't solve the problem of inter-process calls, if that's something desirable. Hmm. Suppose the OS maintained a table of entry points at a fixed address. As processes are loaded any external entry points they have are added to the table. A process can ask the OS for an offset in the table to a particular entry point in some other process, then call it by JMP (fixed_addr,X).

But what if (a) the table fills up as too many processes are loaded or (b) a process is unloaded - can its slots be reclaimed? And what happens if a still-loaded process tries to access it? Oooh - virtual memory.... :shock:


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 2:14 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8540
Location: Southern California
This is sure getting confusing. The relative JMP and JSR take care of the program part of a task, but some equivalent is needed for the data part. That's where I was thinking of having an index register that becomes the offset, and it stays the same for whole task, changing only if the task gets scooted around in memory because something else that got loaded earlier got deleted or needed more room. For the sake of discussion, if X were that offset, LDA abs,Y becomes LDA abs,X,Y for the processor that can do the relocation even after a task is loaded and running, as only X needs to change, not a whole table of addresses. LDA (abs),Y becomes LDA (abs,X),Y, and so on. Accessing data in a common, fixed area available to all tasks just means removing the ",X" from the instruction. OTOH, if another address mode were added that is relative not to an index register but to the current program counter value like the branch instructions, the whole task could be moved without even adjusting the index register. I don't know if there would be any disadvantage to having the data and program areas locked together like that. I can't think of any offhand.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 5:54 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Hi TT
my idea may have been half-baked, so let's see...
teamtempest wrote:
Quote:
So if we added a JMP (address),Y mode we're all set, with minimal change. Although I think that needs quite some change, as it happens.


Mmm...trying to decide if I understand this. JMP (addr,X) I understand: jump to the address stored at memory locations X and X+1 beyond addr. So: add X to addr to get addr+X, then load the two consecutive bytes starting at addr+X into the program counter.

We can use that pre-indexed mode to set up a nice jump table from addr to addr+X.max-1. Okay.
Quote:
Yes, JMP (addr, X) is a jump table, which makes sense even when X's range is terribly small.


But JMP (addr),Y? That's post-indexed, so...how would it work? As near as I can tell it would be: load one byte from addr, add the contents of the Y-register to it, then load a byte from addr+1, add the carry flag to it, and load the resultant two-byte value into the program counter. Yes? So: add Y to (addr) to get (addr)+Y, then jump to that address.

Okay...so you can jump anywhere from (addr) to (addr)+Y.max-1. Hmm. Possibly more useful if Y.max is 65535 rather than 255, although you can change addr itself to anywhere in memory.

Your idea is to set (addr) to zero, then use Y as an offset to the start of any routine within its range? Wouldn't that work for anywhere in memory the code might be loaded only if TBR held the physical base address for translation? But if that's the case, why not simply JMP addr, since TBR will take care of adding the necessary offset anyway?

Or is this instead of a TBR register? Or do I not understand what you're driving at?

Errm, I was trying to counter Garth's suggestions of extra addressing modes. I think he's either shelving or not get grasping the TBR. The TBR allows for tasks which are relocated. Within a task, the addresses and modes all act as they usually do, they just happen to act on an address space which is translated and therefore not the same as physical addresses.

So, JMP (addr),Y can be thought of as a jump to the sum of two things. One is in memory and the other is in Y. If we think of one as a pointer and the other as an offset, we again have a jump table. In the case of the 65Org32 - and this is probably where I've made the unstated mental leap - a full pointer fits in Y. We can place the offset in a single memory location, and we can even set it to zero. Now Y, a register, can hold an address which we can jump to.

I think that's something Garth wanted. In the case of an extended machine with more registers - something which is relatively easy when every instruction fetch is 16 or 32 bits - it might make even more sense.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 5:58 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
GARTHWILSON wrote:
This is sure getting confusing. The relative JMP and JSR take care of the program part of a task, but some equivalent is needed for the data part. That's where I was thinking of having an index register that becomes the offset, and it stays the same for whole task, ... don't know if there would be any disadvantage to having the data and program areas locked together like that. I can't think of any offhand.
I'm certainly confused! Are you casting around for alternatives to TBR, or additions to it? Does your above statement re-invent TBR?? Are you sure you've got the same picture in mind that I have as to what TBR gives you? I sketched a picture up-thread of how the OS could load two tasks, and they could run without any patching or adjustment, and be relocated without any patching or adjustment. I think that's really powerful.

Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 6:51 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
I think the TBR method would work fine. Sure, there are some limitations, but that's what you get for a very simple design. If you wanted to avoid the limitations, you'd have to implement a full blown MMU, and then you'd have bigger problems to solve.

The only thing that doesn't appeal to me is having an extra 32 bit ripple carry delay in the critical path. :)


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 6:53 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8540
Location: Southern California
I guess I just want to make sure there's a light-footedness in a program in going from accessing its own private data to accessing a public data area where its task base register value should not be added to the address in its operands. For my own work, these things cannot be allowed to take the time of referring to OS calls since that takes many instructions' time instead of cranking them out in a few dozen ns.

From a post in another topic but totally related , you say the SEP and REP instructions aren't used often enough to need to do them quickly; but although it's true I did not use them in very many places in my '816 Forth, I would not have been happy if it took many instructions (PHP PLA AND# PHA PLP, 16 clocks) to change the accumulator to 8-bit and back (another 16 clocks) for writing to I/O for example. That would be 26 clocks more than REP and SEP for writing a single byte to I/O. Edit: I went back and looked and I used Y instead of A in some places, where practical, since I kept X & Y in 8-bit mode. That way I didn't have to do REP and SEP.

I agree that the special registers don't need to be in the general register file with all the same capabilities (AND, ORA, EOR, BIT, etc..)

All of this is making me think a lot more than I ever had to about how my real-time work can coexist with multitasking. I'm beginning now to think it can be done--sort of--but not the way common multitasking OSs do it, since they can deprive a task of computer time for even milliseconds, or more, and interrupts have to be disabled for many instrctions' time duration during task switches. [Edit, 5/15/14: I posted an article on simple methods of doing multitasking without a multitasking OS, at http://wilsonminesco.com/multitask/index.html.]

I too am in favor of avoiding the full MMU.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 7:00 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Hi Garth
GARTHWILSON wrote:
I guess I just want to make sure there's a light-footedness in a program in going from accessing its own private data to accessing a public data area where its task base register value should not be added to the address in its operands. For my own work, these things cannot be allowed to take the time of referring to OS calls since that takes many instructions' time instead of cranking them out in a few dozen ns.
All I can offer is the idea of a fixup procedure. You adjust the target addresses in the code which wishes to make physical accesses, just once, and it then runs unhindered at full speed. I can't offer switchable TBR mode. So, I offer fast I/O to trusted tasks. I don't offer inter-task communication or cross-calling, except by BRKing to the OS.
Quote:
From a post in another topic but totally related , you say the SEP and REP instructions aren't used often enough to need to do them quickly; but although it's true I did not use them in very many places in my '816 Forth, I would not have been happy if it took many instructions (PHP PLA AND# PHA PLP, 16 clocks) to change the accumulator to 8-bit and back (another 16 clocks) for writing to I/O for example. That would be 26 clocks more than REP and SEP for writing a single byte to I/O.
Right, but since all sensible people dislike those kinds of modes, we won't be designing them in! So that's OK.
Quote:
I agree that the special registers don't need to be in the general register file with all the same capabilities (AND, ORA, EOR, BIT, etc..)
Great. I'm sure that was just inexperience on EEye's part.
Quote:
All of this is making me think a lot more than I ever had to about how my real-time work can coexist with multitasking. I'm beginning now to think it can be done--sort of--but not the way common multitasking OSs do it, since they can deprive a task of computer time for even milliseconds, or more, and interrupts have to be disabled for many instrctions' time duration during task switches.
You are in control of your own computer, so you get to choose how heavyweight the task 0 workload is, if indeed it is of any use to you. On-request switching sounds more like your kind of thing, rather than timeslicing.
Quote:
I too am in favor of avoiding the full MMU.
Great!
Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 7:04 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
I should add: if several tasks want to access a public data area which isn't moving around much, they could ask the OS for the address (in their terms) and then use that to access it. Each task would be using a different address to access the same data, and those tasks would need to be free of any protection mechanism, so again we'd have to call them trusted tasks, but it could be done.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 7:05 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
GARTHWILSON wrote:
I guess I just want to make sure there's a light-footedness in a program in going from accessing its own private data to accessing a public data area where its task base register value should not be added to the address in its operands. For my own work, these things cannot be allowed to take the time of referring to OS calls since that takes many instructions' time instead of cranking them out in a few dozen ns.

A simple solution could be to divide the memory space into 2 areas. The lower 2GB would have TBR translation, and the upper 2GB would be using straight addresses. Put all your shared data/code in the upper 2GB, and the private stuff in the lower 2GB.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 7:10 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
Arlet wrote:
GARTHWILSON wrote:
I guess I just want to make sure there's a light-footedness in a program in going from accessing its own private data to accessing a public data area where its task base register value should not be added to the address in its operands. For my own work, these things cannot be allowed to take the time of referring to OS calls since that takes many instructions' time instead of cranking them out in a few dozen ns.

A simple solution could be to divide the memory space into 2 areas. The lower 2GB would have TBR translation, and the upper 2GB would be using straight addresses. Put all your shared data/code in the upper 2GB, and the private stuff in the lower 2GB.
It is a solution (mentioned before), but I'm not fond of it! I suppose a generalisation would be a bitmask which means we can set it to zero and then not have this if we don't want it. Somehow I feel more comfortable with a bitmask in a special register than with a mode bit.

Cheers
Ed


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 7:30 am 
Offline
User avatar

Joined: Tue Nov 16, 2010 8:00 am
Posts: 2353
Location: Gouda, The Netherlands
BigEd wrote:
It is a solution (mentioned before), but I'm not fond of it!

Something similar has worked for 32 bit Linux for a long time. User processes only get 3GB, and the kernel gets the other 1GB. It's easy to implement, and it should not affect the critical path as the enable/disable signal for the TBR offset can be incorporated in the same LUTs as the adder. Adding more complicated logic, such as bitmasks, would add another layer of logic.


Top
 Profile  
Reply with quote  
PostPosted: Sat Apr 21, 2012 7:39 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10977
Location: England
That's a good point.


Top
 Profile  
Reply with quote  
PostPosted: Sun Apr 22, 2012 9:53 pm 
Offline

Joined: Tue Jul 05, 2005 7:08 pm
Posts: 1043
Location: near Heidelberg, Germany
GARTHWILSON wrote:
Quote:
Sorry for another plug. My 65k has...

Keep plugging it. Your work is very impressive. You have done a lot of thinking and developing which we ought to be able to take advantage of instead of starting over. However, the web pages, although very neat, make for very difficult reading, so I hope you will continue to explain things.


Please let me know what makes it difficult for you to read the pages. I started working on proper 65002 docs on github, so I want to make it easy to read now. But to avoid thread hijacking let's discuss it in this thread: viewtopic.php?f=10&t=2096

Thanks for any feedback!
André

_________________
Author of the GeckOS multitasking operating system, the usb65 stack, designer of the Micro-PET and many more 6502 content: http://6502.org/users/andre/


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

All times are UTC


Who is online

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