- The cc65 assembler variable 'ptr1' (a general zero page pointer) is actually part of the cc65 zero page area so it's a bad idea (tm) to use it in swapping that very area.

- The cc65 assembler variable 'sp' (the pointer to the C stack) is actually part of the cc65 zero page area so there's no need to manage it explicitly. Furthermore it is known to reside at the very start of the area so it can be initialized there for new threads.
This commit is contained in:
oliverschmidt 2007-08-10 10:45:35 +00:00
parent f8bf3e1428
commit 1c77f6f1d5
3 changed files with 120 additions and 90 deletions

View file

@ -30,15 +30,12 @@
;
; Author: Adam Dunkels <adam@sics.se>
;
; $Id: mtarch-asm.S,v 1.1 2007/04/21 22:15:45 oliverschmidt Exp $
; $Id: mtarch-asm.S,v 1.2 2007/08/10 10:45:35 oliverschmidt Exp $
;
;---------------------------------------------------------------------
.importzp ptr1
.importzp sp
.import __ZP_START__
.import _mtarch_asm_threadspreg
.import _mtarch_asm_threadsp
.import _mtarch_asm_threadzp
.import _mtarch_asm_threadstack
@ -48,68 +45,77 @@
;---------------------------------------------------------------------
.bss
kernelsp: .res 2
kernelspreg: .res 1
kernelspreg: .res 1
zpsave: .res 2
zpsize = 32
zpspace = 26 ; see <cc65 source>/asminc/zeropage.inc
;---------------------------------------------------------------------
.code
; Switch to thread defined by threadsp, threadstack and threadspreg.
; The kernel stack is swapped onto the threadstack, and the
; sp and spreg are saved to the local variables "kernelsp" and
; "kernelspreg". Also, the zeropage variables are saved.
; Switch to thread defined by threadzp, threadstack and threadspreg.
; The kernel CPU stack is swapped onto the threadstack, and the
; CPU stack pointer is saved to the local variable "kernelspreg".
; Also, the zeropage variables are saved.
_mtarch_asm_exec:
sei
; Save current stack pointer
lda sp
sta kernelsp
lda sp+1
sta kernelsp+1
; Save kernel CPU stack pointer
tsx
stx kernelspreg
lda _mtarch_asm_threadzp
sta ptr1
lda _mtarch_asm_threadzp+1
sta ptr1+1
; Save zp locations FE/FF
lda $FE
sta zpsave
lda $FF
sta zpsave+1
; Get zero page buffer addr
lda _mtarch_asm_threadzp
sta $FE
lda _mtarch_asm_threadzp+1
sta $FF
; Swap zero page content with buffer content
ldy #0
: lda <__ZP_START__,y
tax
lda (ptr1),y
lda ($FE),y
sta <__ZP_START__,y
txa
sta (ptr1),y
sta ($FE),y
iny
cpy #zpsize
cpy #zpspace
bne :-
; Get CPU stack buffer addr
lda _mtarch_asm_threadstack
sta ptr1
sta $FE
lda _mtarch_asm_threadstack+1
sta ptr1+1
sta $FF
; Get CPU stack size
ldy kernelspreg ; Determine the smallest of the two stack pointers,
cpy _mtarch_asm_threadspreg ; as we only need to swap the used part of the stack.
bcc :+
ldy _mtarch_asm_threadspreg
; Swap CPU stack content with buffer content
: lda $0100,y
tax
lda (ptr1),y
lda ($FE),y
sta $0100,y
txa
sta (ptr1),y
sta ($FE),y
iny
bne :-
lda _mtarch_asm_threadsp
sta sp
lda _mtarch_asm_threadsp+1
sta sp+1
; Restore zp locations FE/FF
lda zpsave
sta $FE
lda zpsave+1
sta $FF
; Set thread CPU stack pointer
ldx _mtarch_asm_threadspreg
txs
@ -121,10 +127,10 @@ _mtarch_asm_exec:
rti
;---------------------------------------------------------------------
; Switch from thread defined by threadsp, threadstack and threadspreg.
; The kernel stack is swapped back from the threadstack, and the
; sp and spreg are restored from the local variables "kernelsp" and
; "kernelspreg".
; Switch from thread defined by threadzp, threadstack and threadspreg.
; The kernel CPU stack is swapped back from the threadstack, and the
; CPU stack pointer is restored from the local variable "kernelspreg".
; Also, the zeropage variables are restored.
_mtarch_asm_yield:
php
pha
@ -144,54 +150,63 @@ _mtarch_asm_yield:
adc #0
sta $0106,x
lda sp
sta _mtarch_asm_threadsp
lda sp+1
sta _mtarch_asm_threadsp+1
; Save thread CPU stack pointer
tsx
stx _mtarch_asm_threadspreg
lda _mtarch_asm_threadzp
sta ptr1
lda _mtarch_asm_threadzp+1
sta ptr1+1
; Save zp locations FE/FF
lda $FE
sta zpsave
lda $FF
sta zpsave+1
; Get zero page buffer addr
lda _mtarch_asm_threadzp
sta $FE
lda _mtarch_asm_threadzp+1
sta $FF
; Swap zero page content with buffer content
ldy #0
: lda <__ZP_START__,y
tax
lda ($FE),y
sta <__ZP_START__,y
txa
sta ($FE),y
iny
cpy #zpspace
bne :-
; Get CPU stack buffer addr
lda _mtarch_asm_threadstack
sta $FE
lda _mtarch_asm_threadstack+1
sta $FF
; Get CPU stack size
ldy kernelspreg ; Determine the smallest of the two stack pointers,
cpy _mtarch_asm_threadspreg ; as we only need to swap the used part of the stack.
bcc :+
ldy _mtarch_asm_threadspreg
: lda <__ZP_START__,y
tax
lda (ptr1),y
sta <__ZP_START__,y
txa
sta (ptr1),y
iny
cpy #zpsize
bne :-
lda _mtarch_asm_threadstack
sta ptr1
lda _mtarch_asm_threadstack+1
sta ptr1+1
ldy #0
; Swap CPU stack content with buffer content
: lda $0100,y
tax
lda (ptr1),y
lda ($FE),y
sta $0100,y
txa
sta (ptr1),y
sta ($FE),y
iny
bne :-
lda kernelsp
sta sp
lda kernelsp+1
sta sp+1
; Restore zp locations FE/FF
lda zpsave
sta $FE
lda zpsave+1
sta $FF
; Set kernel CPU stack pointer
ldx kernelspreg
txs
@ -199,16 +214,31 @@ _mtarch_asm_yield:
rts
;---------------------------------------------------------------------
_mtarch_asm_start:
lda _mtarch_asm_threadzp
sta ptr1
lda _mtarch_asm_threadzp+1
sta ptr1+1
; Save zp locations FE/FF
lda $FE
sta zpsave
lda $FF
sta zpsave+1
ldy #0
; Get zero page buffer addr
lda _mtarch_asm_threadzp
sta $FE
lda _mtarch_asm_threadzp+1
sta $FF
; Copy zero page content to buffer
ldy #$00
: lda <__ZP_START__,y
sta (ptr1),y
sta ($FE),y
iny
cpy #zpsize
cpy #zpspace
bne :-
; Restore zp locations FE/FF
lda zpsave
sta $FE
lda zpsave+1
sta $FF
rts
;---------------------------------------------------------------------

View file

@ -30,7 +30,7 @@
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: mtarch.c,v 1.1 2007/04/21 22:15:45 oliverschmidt Exp $
* $Id: mtarch.c,v 1.2 2007/08/10 10:45:35 oliverschmidt Exp $
*/
#include <string.h>
@ -38,7 +38,6 @@
#include "mtarch.h"
unsigned char mtarch_asm_threadspreg;
unsigned char *mtarch_asm_threadsp;
unsigned char *mtarch_asm_threadzp;
unsigned char *mtarch_asm_threadstack;
@ -65,6 +64,10 @@ mtarch_start(struct mtarch_thread *thread,
memset(thread->cpustack, 0, sizeof(thread->cpustack));
memset(thread->cstack, 0, sizeof(thread->cstack));
/* Copy current zero page content as template. */
mtarch_asm_threadzp = &(thread->zp);
mtarch_asm_start();
/* Create a CPU stack frame with the appropriate values. */
thread->cpustack[MTARCH_CPUSTACKSIZE - 2] = ((unsigned short)function) / 0x100; /* high byte of return address */
thread->cpustack[MTARCH_CPUSTACKSIZE - 3] = ((unsigned short)function) % 0x100; /* low byte of return address */
@ -75,12 +78,12 @@ mtarch_start(struct mtarch_thread *thread,
thread->spreg = MTARCH_CPUSTACKSIZE - 8;
/* Setup the C stack with the data pointer. */
thread->cstack[MTARCH_CPUSTACKSIZE - 2] = ((unsigned short)data) / 0x100; /* high byte of data pointer */
thread->cstack[MTARCH_CPUSTACKSIZE - 3] = ((unsigned short)data) % 0x100; /* low byte of data pointer */
thread->sp = &thread->cstack[MTARCH_CSTACKSIZE - 3];
thread->cstack[MTARCH_CSTACKSIZE - 2] = ((unsigned short)data) / 0x100; /* high byte of data pointer */
thread->cstack[MTARCH_CSTACKSIZE - 3] = ((unsigned short)data) % 0x100; /* low byte of data pointer */
mtarch_asm_threadzp = &(thread->zp);
mtarch_asm_start();
/* Setup the C stack pointer. */
thread->zp[1] = ((size_t)&thread->cstack[MTARCH_CSTACKSIZE - 3]) / 0x100; /* high byte of C stack pointer */
thread->zp[0] = ((size_t)&thread->cstack[MTARCH_CSTACKSIZE - 3]) % 0x100; /* low byte of C stack pointer */
}
/*--------------------------------------------------------------------------*/
void
@ -95,14 +98,12 @@ mtarch_exec(struct mtarch_thread *thread)
/* Switch processor stack. The call to mtarch_asm_switch() will not
return until the process that we switch to calls yield(). */
mtarch_asm_threadspreg = thread->spreg;
mtarch_asm_threadsp = thread->sp;
mtarch_asm_threadstack = &(thread->cpustack[0]);
mtarch_asm_threadzp = &(thread->zp[0]);
mtarch_asm_threadstack = thread->cpustack;
mtarch_asm_threadzp = thread->zp;
mtarch_asm_exec();
thread->sp = mtarch_asm_threadsp;
thread->spreg = mtarch_asm_threadspreg;
}
/*--------------------------------------------------------------------------*/

View file

@ -30,7 +30,7 @@
*
* Author: Adam Dunkels <adam@sics.se>
*
* $Id: mtarch.h,v 1.2 2007/04/21 22:15:45 oliverschmidt Exp $
* $Id: mtarch.h,v 1.3 2007/08/10 10:45:35 oliverschmidt Exp $
*/
#ifndef __MTARCH_H__
@ -38,11 +38,10 @@
#define MTARCH_CPUSTACKSIZE 256
#define MTARCH_CSTACKSIZE 256
#define MTARCH_ZPSIZE 32
#define MTARCH_ZPSIZE 26 // see <cc65 source>/asminc/zeropage.inc
struct mtarch_thread {
unsigned char spreg;
unsigned char *sp;
unsigned char cpustack[MTARCH_CPUSTACKSIZE];
unsigned char cstack [MTARCH_CSTACKSIZE];
unsigned char zp [MTARCH_ZPSIZE];