Newer
Older
uBix-Retro / dump / oa-2.0.9 / arch / pet32k / kernel / kenv.a65
/****************************************************************************
   
    OS/A65 Version 2.0.0
    Multitasking Operating System for 6502 Computers

    Copyright (C) 1989-1998 Andre Fachat 

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

****************************************************************************/

/* TODO: make stack addr computation a table lookup, which is faster */

/*        Struct Task Environment Entry          */

/* we have three structs now: 
 * TE_* 	for task environment handling - not needed for system without
 *       	memory management
 * TT_*		task table, contains STD streams, etc
 * TH_*		thread table, has stack info and state
 */

#define	TE_SLEN		0	/* we don't have envs */

/************************************************************************
 * These routines are needed in the env section! 
 *   inienv
 *   setthread
 *   initsp
 *   push
 *   pull
 *   memtask
 *   memsys
 *
 *   sbrk
 *   getenv
 *   freenv
 */

&&enmem  = notimp	; to enable memory blocks to the kernel
&&setblk = notimp	; to set memory blocks in MMU mapping

#ifdef STACKCOPY
	.zero
zp	.word 0

	.data

Stacks  .dsb MAXNTHREADS * STACKSIZE

	.text
#endif


&inienv .(
	lda #<-1
	sta actThread
	sta actTask
	lda #1
	sta Syscnt
	clc
	rts
	.)

setthread .(
	.data
newThread .byt 0
	.text

	cmp actThread
	bne doit
	rts
doit
	sta newThread

	ldx actThread
	cpx #<-1
	beq nosave

	lda THREADSAVE
	sta threadTab + TH_LIBSAVE,x
	lda THREADSAVE+1
	sta threadTab + TH_LIBSAVE+1,x

#ifdef STACKCOPY
	txa		; stack is 8 * TH_SLEN = 64
	ldy #0
	sty zp+1
	asl 
	rol zp+1
	asl
	rol zp+1
	asl
	rol zp+1
	clc
	adc #<Stacks
	sta zp
	lda #>Stacks
	adc zp+1
	sta zp+1
	;bcc l1
	;inc zp+1
;l1
	lda threadTab + TH_SP,x
	tay
	iny
l2	cpy #STACKSIZE
	bcs savetask
	lda $100,y
	sta (zp),y
	iny
	bne l2
#endif
savetask
	ldy threadTab + TH_TASK,x
	lda TASKSAVE
	sta taskTab + TT_LIBSAVE,y
	lda TASKSAVE + 1
	sta taskTab + TT_LIBSAVE + 1,y
nosave	
loadtask
	ldx newThread
	stx actThread
	cpx #<-1
	bne load
	stx actTask
	beq noload
load
	ldy threadTab + TH_TASK,x
	sty actTask

	lda taskTab + TT_LIBSAVE,y
	sta TASKSAVE
	lda taskTab + TT_LIBSAVE + 1,y
	sta TASKSAVE + 1

loadthread 
	lda threadTab + TH_LIBSAVE,x
	sta THREADSAVE
	lda threadTab + TH_LIBSAVE+1,x
	sta THREADSAVE+1

#ifdef STACKCOPY
	txa
	ldy #0
	sty zp+1
	asl 
	rol zp+1
	asl
	rol zp+1
	asl
	rol zp+1
	clc
	adc #<Stacks
	sta zp
	lda #>Stacks
	adc zp+1
	sta zp+1
	;bcc l3
	;inc zp+1
;l3
	lda threadTab + TH_SP,x
	tay
	iny
l4	cpy #STACKSIZE
	bcs endset
	lda (zp),y
	sta $100,y
	iny
	bne l4
#endif
noload
endset	rts
	.)

initsp	.(
#ifdef STACKCOPY
	lda #STACKSIZE-1
	;ldx actThread
	sta threadTab + TH_SP,x
	rts
#else
	.data
divsp	.byt 0
	.text

	;ldx actThread
	txa
	clc
	adc #TH_SLEN
	sta divsp
	asl
	asl				; split stack
	clc
	adc divsp
	sta threadTab + TH_SP,x
	dec threadTab + TH_SP,x
	rts
#endif
	.)

pull	.(
	ldx actThread
	inc threadTab + TH_SP,x
	lda threadTab + TH_SP,x
	tay
	lda $0100,y
	rts
	.)

&push	.(
	pha
	ldx actThread
	lda threadTab + TH_SP,x
	tay
	pla
	sta $0100,y
	dec threadTab + TH_SP,x
	rts
	.)

	.(
	.zero
AC      .byt 0
XR      .byt 0
YR      .byt 0
SR      .byt 0
ADR     .word 0
&SSP    .byt 0
	.text

/* 
 * this one is used to return from an interrupt. We do not need to save
 * any registers. so for brevity, we do it as macro
 * This doesn't check for interrupted devices, as we do not have them 
 * without MMU (so far).
 */

#define MEMTASK2()                                      \
	.(						:\
	  sei						:\
	  dec Syscnt					:\
	  bne mtask					:\
          tsx                                           :\
          stx SSP                                       :\
;          ldy actTask					:\
;          ldx taskTab+TT_ENV,y				:\
;          beq system					:\
;          ldx #%10001100				:\
;          stx $fff0					:\
;system							:\
          ldy actThread                                 :\
          ldx threadTab+TH_SP,y                         :\
          txs						:\
mtask	.)

/* 
 * This is the standard return to user space. the kernel jumps here,
 * so we need not save any return address, but use the one on the
 * user stack.
 */
&&memtask .(
	  php
          sei
          dec Syscnt     ; wieder in Task 
          bne mtask      ; nein dann Ende

          bit adev       ; Ruecksprung in Device
          bpl mtask      ; ja dann Ende
 
          sty YR         ; sonst Task-Env setzen
          stx XR
          sta AC
          pla		 ; SR

          tsx
          stx SSP

          ldy actThread
          ldx threadTab+TH_SP,y 
          txs

;	  ldy actTask
;	  ldx taskTab+TT_ENV,y
;	  beq system
;	  ldx #%10001100	; map alternate 8x96 memory bank
;	  stx $fff0
;system

          pha		 ; SR
          lda AC
          ldy YR
          ldx XR
mtask     
	  plp
          rts
	  .)

/* 
 * This is the kernel entry routine. It leaves all registers as they
 * are, except for the stack pointer, which is set to the system stack.
 * also the return address is moved from user stack to system stack,
 * to allow "JSR"-ing to memsys.
 */
&&memsys  php
          sei
          pha

;	  lda #%11100000	; map system memory
;	  sta $fff0

          lda Syscnt
          inc Syscnt
          cmp #0
          bne mse
          bit adev       ; called by device
          bmi msys       ; no then save stack
mse       pla
          plp
          rts

msys      pla
          sta AC
          pla
          sta SR
          stx XR
          ; sty YR
          pla
          sta ADR
          pla
          sta ADR+1
          tsx

          txa
          ldx actThread
          sta threadTab+TH_SP,x
          ldx SSP
          txs
          lda ADR+1
          pha
          lda ADR
          pha
          lda SR
          pha
          lda AC
          ldx XR
          ; ldy YR
          plp
          cld
          rts
	.)


&&sbrk	.(
	bcc ok
	sec
	lda #E_NOMEM
	rts
ok	lda #>ROMSTART		; return available memory
	clc
	rts
	.)

kgetenv	.(
	ldx #0
;	tya
;	bne system
;	inx
system  
	clc
	rts
	.)

freenv	.(
	clc
	rts
	.)

/*
 * MAPSYSBUF() maps the PCBUF of the active task into the system memory
 * at address SYSBUF. It's not needed in a C64...
 */
#undef	MAPSYSBUF
#define	SYSBUF	$200

/*
 * MAPENV() maps the address given in a/y in env x to somewhere in the 
 * kernel map. returns mapped address in a/y
 * MAPAENV() does the same but for the actual task (env)
 */
#define	MAPENV()
#define	MAPAENV()


/*
 * needed for GETINFO, gives RAM available for task
 */
#define	GETTASKMEM	lda #>ROMSTART

/*
 * copy routines for SEND/RECEIVE and FORK
 */
#undef CPPCBUFRX
#undef CPPCBUFTX
#define	CPFORKBUF()

/*
 * needed in device code to get active environment in AC
 */
#define GETACTENV()     lda #<-1