Close

CMS9639 specific changes OS9p1

A project log for 6809/6309 Eurocard CPU System

A retrosystem based on the elegant 8/16 bit 6809 processor capable of running UniFLEX and OS9 level II multiuser/multitasking OS

roelof4roelof4 04/02/2026 at 11:290 Comments

This first part of the OS-9 level 2 kernel (OS9p1) provides essential system calls that make up the operating system allowing proper task administration, memory management, etc.

Comparing the OS9p1 used for the CMS9639 with standard OS9p1 code it is clear that there are three low-level functions that have changed. All three are involved with moving data between tasks and in the case of the CMS9639 the memory-to-memory DMA facility is used even if there is only one byte to be moved.

Here, we don't consider changes in setting up/checking memory and the Data Address Translator (DAT, key part of the MMU) initialisation since these would be different for any system.

The changes are found in the code for Mover(00)/MoveRegs, PutRegs and STABX/LDABX (using source code labels). Below the difference between standard and CMS9639 is shown for PutRegs, which copies registers between tasks.

Below we compare PutRegs:

CMS9639:

************************************************************
*
* Subroutine PutRegs
*
* Copy User interrupt register stack
*
* Input: X = Process Descriptor ptr
* U = local stack ptr
*
* Output: none
*
* Data: none
*
* Calls: uses DMA to copy register stack
*
PutRegs ldb P$Task,X get process task
 andb #^SysTask
 clra
 pshs u,x,cc
 ldx P$SP,X get process stack ptr
 exg x,u switch source & destination
PutReg.A equ *
 orcc #IntMasks
 sta >Tsk.Src Task to copy from
 stx >$FFC0 DMAC source address register
 stu >$FFC4 DMAC destination address register
 ldx #R$Size
 stx >$FFC2 DMAC Source byte count register
 stx >$FFC6 DMAC Destination byte count register
 stb >Tsk.Dst Task to copy to
 ldb #$03
 stb >ContrlSW send command
 nop
 puls pc,u,x,cc

Standard: 

************************************************************
*
*     Subroutine PutRegs
*
*   Copy User interrupt register stack
*
* Input: X = Process Descriptor ptr
*        U = local stack ptr
*
* Output: none
*
* Data: none
*
* Calls: MoveRegs
*
PutRegs ldb P$Task,x get process task
 lda D.SysTsk get system stack
 pshs u,y,x,DP,D,CC save registers
 ldx P$SP,x get process stack ptr
 exg x,u switch source & destination
PutReg.A equ *
 ldy #R$Size/2 get double byte count
 tfr B,DP copy process task
 orcc #IntMasks set interrupt masks
 lbra MoveRegs 
Mover10 lda 1,s get source task number
 orcc #IntMasks set interrupt masks
MoveRegs sta DAT.Task set source task
 ldd ,x++ get data double byte
 exg b,dp switch data & task
 stb DAT.Task
 exg b,dp switch back
 std ,u++
Mover30 lda #SysTask get system task
 sta DAT.Task set system task
 lda 0,s get previous masks
 tfr a,cc reset interrupt masks
 leay -1,y count double byte
 bne Mover10 branch if more
 puls pc,u,y,x,dp,d,cc

The DMA version essentially uploads source and destination information and moves bytes during DMA just after 3 is written to the ControlSwitch (ARM DMA). Task switching is automatic between source and destination.

For the standard case there is changing of task needed for every (double)byte. R$Size is the number of bytes to move.

Apart from the data moving routines there is one further CMS9639 specific change that is at the heart of system calls. System calls use a SWI2 software interrupt followed by a PostByte which indicates what system call is to be performed. Normally software collects the PostByte from user space and increments the program counter to skip the PostByte upon return. The CMS9639 has a dedicated circuit that captures the PostByte and places it in memory location $FFFA0. It also increments the program counter before placing it on the stack.

In the snippet from OS9p1 this process can be found in detail for both cases using conditional assembly:

************************************************************
*
* System Service Request Routine
*
* Process system service requests
*
* Input: S = value of stack after interrupt
*
* Output: none
*
* Data: D.SysDis, D.SysPrc
*
* Calls: Dispatch, SysRet
*
SysSvc leau 0,s get registers ptr
 ifeq CPUType-CMS9639
 ldb Postbyte get service code
 lda R$CC,u get caller's interrupt masks
 tfr a,cc restore interrupt masks
 else
 lda R$CC,u get caller's interrupt masks
 tfr a,cc restore interrupt masks
 ldx R$PC,u get program counter
 ldb ,x+ get service code
 stx R$PC,u update program counter
 endc
 ldy D.SysDis get system dispatch table ptr
 bsr Dispatch dispatch to service routine
 lbra SysRet

Discussions