.i8
.a8
lda U_DATA__U_PAGE
- sta switch_patch_1+2 ; target bank of save
+ sta switch_patch_1+1 ; target bank of save
rep #$30
.i16
.a16
; FIXME: add swap support
;
_switchin:
+ ; not in theory needed
+ sep #$30
+ .i8
+ .a8
+
sei
sta ptr1
stx ptr1+1
- sep #$30
- .i8
- .a8
ldy #P_TAB__P_PAGE_OFFSET
lda (ptr1),y ; bank of target
; If this is zero we need swapping so the swapper checks go here
; FIXME
- sta switch_patch_2+1 ; source bank of retrieve
+ sta switch_patch_2+2 ; source bank of retrieve
rep #$30
.i16
.a16
; Set our stack pointer. We must not use it until the mvn
; is completed
- ldx U_DATA__U_SP ; correct stack pointer
- txs
ldx #U_DATA_STASH
- ldx #U_DATA
+ ldy #U_DATA
lda #U_DATA__TOTALSIZE-1
switch_patch_2:
; FIXME check syntax required for bank value ??
- mvn 0,KERNEL_FAR
+ mvn KERNEL_FAR,0
; after the MVN our data bank is KERNEL_DATA
; Our stack is now valid and we may use it again, our UDATA
; is for the new process
+ ldx U_DATA__U_SP ; correct stack pointer
+ txs
ldx U_DATA__U_PTAB
cpx ptr1
bne switchinfail ; wrong process !!
; This will only be needed once we swap, and we will need to
; do a few other fixups too
lda P_TAB__P_PAGE_OFFSET,x
- sta U_DATA__U_PAGE,x
+ sta U_DATA__U_PAGE
plx ; stacked kernel space C sp
stx sp
sep #$10
beq notisr
cli ; interrupts back on
notisr:
- plx ; return code
- pla
+ pla ; return code
+ plx
rts
switchinfail:
+ sep #$30
+ .a8
+ .i8
lda ptr1+1
jsr outcharhex
lda ptr1
stx ptr1+1
lda U_DATA__U_PAGE
sta fork_patch+2 ; source bank (parent)
+ sta fork_patch_2+1 ; destination udata stash
asl a
adc #STACK_BANKOFF
- sta tmp1+1 ; source for S and DP
- stz tmp1
+ sta ptr2+1 ; source for S and DP
+ stz ptr2
ldy #P_TAB__P_PAGE_OFFSET
lda (ptr1),y
sta fork_patch+1 ; destination bank (child)
- sta fork_patch_2+1
asl a
adc #STACK_BANKOFF ; find our S and DP banks as
; those need copying too
- sta tmp2+1 ; dest for S and DP
- stz tmp2
+ sta ptr3+1 ; dest for S and DP
+ stz ptr3
rep #$20
.a16
tsx
stx U_DATA__U_SP ; Stack pointer in udata
- ; Our context is now a valid child stack frame so we can save stuff
+ ; Our context is now a valid stack frame so we can save stuff
ldx #0
txy
lda #MAP_SIZE ; 64K - udata shadow
mvn KERNEL_FAR,0
plb ; back to kernel bank
- ldx tmp1
- ldy tmp2
+ ldx ptr2
+ ldy ptr3
lda #$01FF ; DP and stack
mvn 0,0
; versus parent so we restore it correctly
;
+ sep #$30
+ .a8
+ .i8
lda U_DATA__U_SYSCALL_SP+1
- clc
- adc tmp1
sec
- sbc tmp2
+ sbc ptr2+1
+ clc
+ adc ptr3+1
sta U_DATA__U_SYSCALL_SP+1
+ rep #$10
+ .i16
+
; At this point we have copied the parent into the child bank
; and copied the current uarea into the child uarea
- plx ; discard frame we build for child
+ plx ; discard frame we build for parent
plx
sep #$30 ; back to 8bit mode for C
; registers and return directly to the start of the user process
;
_doexec:
- sta tmp1
- stx tmp1+1 ; address to execute from
+ sta ptr1
+ stx ptr1+1 ; address to execute from
sei
stz _kernel_flag
.i16
.a16
- ldx tmp1 ; target address
+ ldx ptr1 ; target address
sep #$20
.a8
; caller already saved the CPU state. Interrupts are off at this point
; as it we got here via a trap.
;
+; FIXME save the right registers to return correctly if caught
+;
shoot_myself:
sep #$30
.a8
pha
phx
phy
+ phb
+ phd
cld ; no funnies with decimal
; Now switch our data and DP to the kernel ones
lda _kernel_flag
beq ret_to_user
- lda #KERNEL_BANK
- pha
- plb
- ldx #KERNEL_DP
- phx
+ ; Kernel interrupt path may change B and D itself so we must
+ ; preserve them
+
pld
+ plb
rep #$20
.a16
ret_to_user:
; TODO .. pre-emption
+ ; Discard saved B and D - for user we will compute the correct
+ ; one (we could optimize this a shade and only throw on a
+ ; pre-empt FIXME)
+
+ plx
+ pla
+
; Signal return path
; The basic idea here is that if a signal is pending we
jsl KERNEL_FAR+syscall_entry
rts
+;
+; Relocation stub (as it's easier to do relocation when in the user
+; bank than bouncing around and we have no common!). Called with i16
+; and X holding the binary start, tmp1 the shift and Y the code to
+; process
+;
+; Returns with X pointing to end zero (so we can run it twice to do
+; ZP). We wipe the data as we go since it will become BSS.
+;
+; Our relocation table lives in BSS start and is a byte table in the
+; format
+; 0,0 end
+; 0,n skip n bytes and read next table entry
+; 1-255 skip 1-255 bytes and relocate the byte now pointed at
+; then read next table entry
+;
+; Our first table is high bytes of 16bit addresses to relocate (we
+; keep page alignment). Our second is ZP addresses to relocate.
+;
+; Call with interrupts off until sure our irq code will get odd
+; code banks right.
+;
+; FIXME: move out of stubs - run with code = normal dp = kernel
+; b = user and it'll work better
+;
+; FIXME: consider checking if run off end with either X or Y
+;
+relocate:
+ .i16
+ .a8
+ stz tmp2+1 ; FIXME
+reloc_loop:
+ lda 0,x
+ stz 0,x
+ beq multi
+ sta tmp2
+ ; skip 1-255 bytes and then relocate one byte
+ rep #$20
+ .a16
+ tya
+ adc tmp2
+ tay
+ sep #$20
+ .a8
+ ; now relocate
+ lda 0,y
+ clc
+ adc tmp1
+ sta 0,y
+ bra reloc_loop
+multi:
+ .i16
+ .a8
+ inx
+ lda 0,x
+ stz 0,x
+ beq endofreloc ; (0,0 -> end)
+ sta tmp2
+ rep #$20
+ .a16
+ tya
+ adc tmp2
+ tay
+ sep #$20
+ .a8
+ bra reloc_loop
+endofreloc:
+ rtl ; as called from bank KERNEL
+
;
; ptr1 and tmp1 are reserved for map_* functions in 6502 but
-; are actually free here. We keep the convention however in case
-; of future changes
+; are actually free here.
;
.code
; Compiler glue is not pretty - might be worth having some optimized
; 16bit aware stack handlers
;
-__uget: sta tmp2
- stx tmp2+1 ; save the count
+__uget: sta ptr1
+ stx ptr1+1 ; save the count
jsr popax ; pop the destination
sta ptr2 ; (ptr2) is our target
stx ptr2+1
- jsr popax ; (ptr2) is our source
+ jsr popax ; (ptr3) is our source
sta ptr3
stx ptr3+1
lda U_DATA__U_PAGE
- sta ugetpatch+1
+ sta ugetpatch+2
phb
.i16
.a16
rep #$30
ldx ptr3 ; source
ldy ptr2 ; destination
- lda tmp2
+ lda ptr1
beq ug_nomov ; 0 means 64K!
dec ; need 1 less than size
ugetpatch:
__uput:
- sta tmp2
- stx tmp2+1
+ sta ptr1
+ stx ptr1+1
jsr popax ; dest
sta ptr2
stx ptr2+1
rep #$30
ldx ptr3 ; source
ldy ptr2 ; destination
- lda tmp2
+ lda ptr1
beq up_nomov ; 0 means 64K!
dec ; need 1 less than size
uputpatch:
stx ptr2+1
jsr popax
phb
+ pha
lda U_DATA__U_PAGE
pha
plb
+ pla
sta (ptr2)
plb
+ lda #0
+ tax
rts
__uputw:
ldy #1
sta (ptr2),y
plb
+ lda #0
+ tax
rts
__uzero: