6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Wed May 15, 2024 7:35 am

All times are UTC




Post new topic Reply to topic  [ 20 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Fri Jan 18, 2019 7:15 am 
Online
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10800
Location: England
That does sound like a good idea. Acorn's OSWORD interface is similar, in that a parameter block is passed (the address is passed in X and Y) and that block of memory can be used both for inputs and outputs. Using the stack makes sense, on a processor which has good stack access (and lots of stack space).


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 12, 2019 5:21 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
BitWise wrote:
BigEd wrote:
One of the simple and tempting things to do to improve the '816 memory map is to hide the vectors until they are needed (using the vector pull signals) - that works well with COP but not with jumps. With the OS in low memory you can then have contiguous memory starting part way through bank 0.

But the vectors are only two bytes each so at some point you have to have some executable code in bank 0 either in a ROM or bootstrapped into RAM prior to power on.

You can also use the method of interrupt vectoring used on some Z80 and 8080 systems: when VPB is asserted, feed two bogus bytes to the CPU (you won't be needing them), followed immediately by a JML instruction to the desired 24-bit address. At the cost of a few extra cycles for handling interrupts, you can place your ISR anywhere in memory. Moreover, each device can have its own vector, so you can save yourself the cost of polling in software. With enough devices, this can even lead to a net savings in ISR response time.

This approach can also be extended to handle COP and BRK vectors too. When VPA is asserted and the data bus reads $02 or $00 (respectively), this same hardware can load the JML instruction to the COP-/BRK-handler. You'll need the help of a CPLD (at least) to implement this in a space-efficient manner, but it ought to be well within the realm of feasibility.


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 12, 2019 5:40 am 
Offline

Joined: Sat Jan 04, 2003 10:03 pm
Posts: 1706
The other thing that I've not seen mentioned is the JMP ($xxxx,X) instruction. Load the function ID into X (ensuring bit 0 is clear), then JML, BRK, or COP. That leaves A,Y for passing an address to a parameter block, or using the stack.

The reason you want to avoid using a single COP and a single pool of function IDs as BDD feels more comfortable with is because there is **zero** performance advantage and **negative** usability advantages to monolithic kernels on the 65xx architecture. You absolutely want the ability to dynamically load and unload modules/libraries (exactly the same thing in 65xx land), and these modules can be (and almost certainly will be) loaded at a different address every time you load them.

So, if you use COP, you'll want one register to select which module you're addressing, and X to select a function within that module. A better solution is to use a well-known kernel function similar to Amiga's OpenLibrary() call which manages library sharing and lifecycle, and returns the address of the library just opened (thus, if three processes all use the same library, they will all get the same address back). This pointer can be saved into your program's data area like so:

Code:
; somehow get address of library in A,X
sta libA+1
stx libA+3
php
sep #$30
lda #OPCODE_JML
sta libA
plp


For example, here's how I'd 65816-ize the start-up code found in Tripos-compatible applications, assuming someone were to port Tripos to the 65816:

Code:
_start:
  ; First, call the kernel to find our DOS entrypoint.

  ldx #sc_FindDos
  cop #0
  sta DosLib+1
  stx DosLib+3

  ; Now, open a file, then close it again, just because we can.

  pea #MODE_OLD
  pea #>filename
  pea #<filename
  ldx #LVO_Open
  jsl DosLib

  ; A already has the reference to the SCB if the file existed.
  ; For brevity, I omit error handling.

  pha
  ldx #LVO_Close
  jsl DosLib

  ; Clean up the stack.  If we used more than 4 slots,
  ; then TSC;ADC;TCS would be smaller.

  plx
  plx
  plx
  plx

  ; Exit back to the shell.

  ldx #LVO_Exit
  pea #0
  jsl DosLib  ; never returns.

  .data
DosLib:
  jml $000000

filename:
  .byte "RAM:Foo/Bar",0


As you can see, now you can call the library directly without incurring any kernel overhead by loading your function selector in X and executing JSL libA. Easy peasy, it's probably the 2nd or 3rd fastest method of invoking services on a 65xx CPU (you might remember an earlier set of reasoning I did here on these forums a decade or so ago about how to support OOP dispatch -- it's exactly the same problem), and it's infinitely (RAM permitting) open-ended. You're not limited to just what the kernel offers in functionality. (While I enjoy the everything-is-a-file metaphor, I don't believe it should be followed religiously. There are legitimate counter-cases where this is demonstrably not true, such as GUIs).


Top
 Profile  
Reply with quote  
PostPosted: Wed Apr 24, 2019 3:50 pm 
Offline

Joined: Mon Jun 24, 2013 8:18 am
Posts: 83
Location: Italy
Just as contribution to this discussion, in my c16 computer i'm developing system calls through 'cop' instruction; i use 'signature byte' as 'function number'.
For example, printing a character to console, is accomplished with this code:

Code:
lda #'A'
cop $00


The code i use for cop handler can be see at http://65xx.unet.bz/c16sw/index.php.
Error condition is returned raising the carry flag (the error code in lower byte of y register).
System functions can reside anywhere in memory, but not in bank 0, and parameters can be
passed through registers or/and through stack.
The table that hold the system function address (3-bytes) use a 4-th byte for hold the count
of bytes passed on stack (for clean stack when cop handler exit).

Marco

_________________
http://65xx.unet.bz/ - Hardware & Software 65XX family


Top
 Profile  
Reply with quote  
PostPosted: Mon May 30, 2022 8:13 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8183
Location: Midwestern USA
A bump to this topic.

Starting with POC V1.3, the BIOS API is called using COP #N, where N is the desired service number.  I had also tried out a BIOS version that used JSL to called APIs, but determined that using COP produced smaller code, both in the BIOS itself and in the applications that call for API services.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


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

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: