# HG changeset patch # User Paul Boddie # Date 1435512186 -7200 # Node ID b639ee361009a584e94b2d1178b396451af3928b # Parent c9cc853003d339d4fe204cc25b2f3366509de441 Introduced a simpler way of invoking subroutines with the user stack, employing explicit return addresses. Changed the user stack layout slightly to support jumping to stored addresses more conveniently. Modified the third example task somewhat. Reinstated return values for the new_task subroutine. diff -r c9cc853003d3 -r b639ee361009 macros.oph --- a/macros.oph Sun Jun 28 15:45:29 2015 +0200 +++ b/macros.oph Sun Jun 28 19:23:06 2015 +0200 @@ -144,6 +144,8 @@ ; ; _1: valueW ; _2: {valueL, valueH} -> {valueL', valueH'} +; +; affects: A, C .macro sub16 sec @@ -165,52 +167,81 @@ adc #1 .macend -; push PC onto a "user space" stack and jump to subroutine +; push A onto the "user space" stack, adding an empty byte for compatibility +; with PC storage ; -; _1: target - -.macro call - sei ; prevent CPU stack disturbance - jsr copy_to_user_stack - cli ; permit CPU stack access again - jmp _1 - nop -.macend - -; pull PC from a "user space" stack and return from subroutine - -.macro return - jmp copy_from_user_stack -.macend - -; push A onto the "user space" stack -; -; affects: USER (gains A), TEMP +; affects: USER (gains empty, A), TEMP .macro pushA sei + php pha sty TEMP ldy #0 sta (USER), y - .invoke sub16 1, USER + .invoke sub16 2, USER ldy TEMP pla + plp cli .macend ; pull A from the "user space" stack ; -; affects: A, USER (loses A), TEMP +; affects: A, USER (loses empty, A), TEMP .macro pullA sei + php sty TEMP - .invoke add16 1, USER + .invoke add16 2, USER ldy #0 lda (USER), y ldy TEMP + plp cli .macend +; push a return address onto the "user space" stack and jump to a subroutine +; +; _1: subroutine address +; _2: return address +; +; affects: USER (gains LSB, MSB), TEMP + +.macro call + sei + php + pha + sty TEMP + ldy #0 + lda #<_2 + sta (USER), y + iny + lda #>_2 + sta (USER), y + .invoke sub16 2, USER + ldy TEMP + pla + plp + cli + jmp _1 +.macend + +; pull an address from the "user space" stack and return to it +; +; affects: USER (loses LSB, MSB), ABSTEMP + +.macro return + sei + php + pha + .invoke add16 2, USER + .invoke mov16_from_ref USER, ABSTEMP + pla + plp + cli + jmp (ABSTEMP) +.macend + ; vim: tabstop=4 expandtab shiftwidth=4 diff -r c9cc853003d3 -r b639ee361009 switcher.oph --- a/switcher.oph Sun Jun 28 15:45:29 2015 +0200 +++ b/switcher.oph Sun Jun 28 19:23:06 2015 +0200 @@ -38,7 +38,8 @@ ; "user space" stack for the main program where the invocations might be ; interrupted and where the CPU stack might be disrupted -.alias main_stack $1fff +.alias main_stack $1ffc +.alias ABSTEMP $1ffe @@ -50,135 +51,20 @@ ; main program, installing the handler and adding example tasks main: - jsr install_handler .invoke store16 tasks, ARG1 .invoke store16 main_stack, USER .invoke store16 first_task, ARG0 - .invoke call new_task - .invoke store16 second_task, ARG0 - .invoke call new_task - .invoke store16 third_task, ARG0 - .invoke call new_task + .invoke call new_task, + +* .invoke store16 second_task, ARG0 + .invoke call new_task, + +* .invoke store16 third_task, ARG0 + .invoke call new_task, + +* jsr install_handler wait: jmp wait ; wait for the switcher to take over -; move CPU stack data to the "user space" stack -; -; affects: USER (gains LSB, MSB) - -copy_to_user_stack: - pha ; A -> stack - txa - pha ; X -> stack - tsx ; capture the stack pointer now for later use - ; (stack is Y, X, A, LSB, MSB) - tya - pha ; Y -> stack - - ; save zero-page locations used - - .invoke push16 SP - - ; initialise the stack frame pointer - - txa - sta SP - lda #$01 ; $01xx - sta SPH - - ; allocate "user space" stack space to be compatible with the CPU stack - - .invoke sub16 5, USER - - ; copy the PC, updated by 4 (see the call macro) - - ldy #3 - clc - lda (SP), y - adc #4 - sta (USER), y - iny - lda (SP), y - adc #0 - sta (USER), y - - ; correct "user space" stack - - .invoke add16 3, USER - - ; restore zero-page locations used - - .invoke pull16 SP - - ; return to the caller - - pla - tay ; stack -> Y - pla - tax ; stack -> X - pla ; stack -> A - rts - - - -; move CPU stack data from the "user space" stack -; -; affects: USER (loses LSB, MSB) - -copy_from_user_stack: - pha ; padding - pha ; padding - pha ; A -> stack - txa - pha ; X -> stack - tsx ; capture the stack pointer now for later use - ; (stack is Y, X, A, LSB, MSB) - tya - pha ; Y -> stack - - ; save zero-page locations used - - .invoke push16 SP - - ; initialise the stack frame pointer - - txa - sta SP - lda #$01 ; $01xx - sta SPH - - ; adjust the "user space" stack pointer to be compatible with the PC stack - - .invoke sub16 3, USER - - ; copy the PC - - ldy #3 - .invoke mov8_refs USER, SP - iny - .invoke mov8_refs USER, SP - - ; update the "user space" stack pointer - - .invoke add16 5, USER - - ; restore zero-page locations used - - .invoke pull16 SP - - ; return to the stored PC - - pla - tay ; stack -> Y - pla - tax ; stack -> X - pla ; stack -> A - rts - - - ; install the interrupt handler address in IRQ1V ; ; affects: A @@ -342,6 +228,7 @@ ; ; ARG0, ARG0H: location of task structure ; affects: A, Y +; returns: 0 if successful, 1 if unsuccessful new_task: @@ -374,9 +261,11 @@ sta tasks, y cli + lda #0 .invoke return no_new_task: + lda #1 .invoke return @@ -438,24 +327,30 @@ .word third_task_start ; saved PC third_task_start: ldx #0 - ldy #0 +_begin: + ldy #0 ; reset counter LSB + lda #0 ; reset counter MSB + sta $7011 _loop: + sty $7010 cpy #$ff bne _continue - inc $7011 - lda $7011 + clc + lda $7011 ; next MSB + adc #1 + sta $7011 cmp #$ff bne _continue - tya + txa .invoke pushA - txa - .invoke call remove_task - .invoke pullA - tay - inx + .invoke call remove_task, + +* .invoke pullA + tax + inx ; move to next offset + inx ; which is 2 locations away + jmp _begin _continue: iny - sty $7010 jmp _loop third_task_stack: .word 0 @@ -463,7 +358,7 @@ .word 0 .word 0 .word 0 +third_task_stack_base: .word 0 -third_task_stack_base: ; vim: tabstop=4 expandtab shiftwidth=4