- 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:
parent
f8bf3e1428
commit
1c77f6f1d5
3 changed files with 120 additions and 90 deletions
|
@ -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
|
||||
;---------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
|
|
@ -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];
|
||||
|
|
Loading…
Reference in a new issue