1.1 --- a/switcher.oph Sat Jun 27 20:35:31 2015 +0200
1.2 +++ b/switcher.oph Sun Jun 28 14:08:35 2015 +0200
1.3 @@ -25,24 +25,158 @@
1.4 .alias NEXTH $73
1.5 .alias CURRENT $74
1.6 .alias CURRENTH $75
1.7 +.alias USER $76
1.8 +.alias ARG0 $80
1.9 +.alias ARG0H $81
1.10 +.alias ARG1 $82
1.11 +.alias ARG1H $83
1.12
1.13 .alias TASK_TABLE_LENGTH 10
1.14
1.15 +; "user space" stack for the main program where the invocations might be
1.16 +; interrupted and where the CPU stack might be disrupted
1.17 +
1.18 +.alias main_stack $1fff
1.19 +
1.20 +
1.21 +
1.22 .org $2000
1.23 .text
1.24 +
1.25 +
1.26 +
1.27 +; main program, installing the handler and adding example tasks
1.28 +
1.29 main:
1.30 jsr install_handler
1.31 - .invoke store16 first_task, $76
1.32 - jsr new_task
1.33 - .invoke store16 second_task, $76
1.34 - jsr new_task
1.35 - .invoke store16 third_task, $76
1.36 - jsr new_task
1.37 + .invoke store16 tasks, ARG1
1.38 + .invoke store16 main_stack, USER
1.39 + .invoke store16 first_task, ARG0
1.40 + .invoke call new_task
1.41 + .invoke store16 second_task, ARG0
1.42 + .invoke call new_task
1.43 + .invoke store16 third_task, ARG0
1.44 + .invoke call new_task
1.45 wait:
1.46 jmp wait ; wait for the switcher to take over
1.47
1.48
1.49
1.50 +; move CPU stack data to the "user space" stack
1.51 +;
1.52 +; affects: USER (gains LSB, MSB)
1.53 +
1.54 +copy_to_user_stack:
1.55 + pha ; A -> stack
1.56 + txa
1.57 + pha ; X -> stack
1.58 + tsx ; capture the stack pointer now for later use
1.59 + ; (stack is Y, X, A, LSB, MSB)
1.60 + tya
1.61 + pha ; Y -> stack
1.62 +
1.63 + ; save zero-page locations used
1.64 +
1.65 + .invoke push16 SP
1.66 +
1.67 + ; initialise the stack frame pointer
1.68 +
1.69 + txa
1.70 + sta SP
1.71 + lda #$01 ; $01xx
1.72 + sta SPH
1.73 +
1.74 + ; allocate "user space" stack space to be compatible with the CPU stack
1.75 +
1.76 + .invoke sub16 5, USER
1.77 +
1.78 + ; copy the PC, updated by 4 (see the call macro)
1.79 +
1.80 + ldy #3
1.81 + clc
1.82 + lda (SP), y
1.83 + adc #4
1.84 + sta (USER), y
1.85 + iny
1.86 + lda (SP), y
1.87 + adc #0
1.88 + sta (USER), y
1.89 +
1.90 + ; correct "user space" stack
1.91 +
1.92 + .invoke add16 3, USER
1.93 +
1.94 + ; restore zero-page locations used
1.95 +
1.96 + .invoke pull16 SP
1.97 +
1.98 + ; return to the caller
1.99 +
1.100 + pla
1.101 + tay ; stack -> Y
1.102 + pla
1.103 + tax ; stack -> X
1.104 + pla ; stack -> A
1.105 + rts
1.106 +
1.107 +
1.108 +
1.109 +; move CPU stack data from the "user space" stack
1.110 +;
1.111 +; affects: USER (loses LSB, MSB)
1.112 +
1.113 +copy_from_user_stack:
1.114 + pha ; padding
1.115 + pha ; padding
1.116 + pha ; A -> stack
1.117 + txa
1.118 + pha ; X -> stack
1.119 + tsx ; capture the stack pointer now for later use
1.120 + ; (stack is Y, X, A, LSB, MSB)
1.121 + tya
1.122 + pha ; Y -> stack
1.123 +
1.124 + ; save zero-page locations used
1.125 +
1.126 + .invoke push16 SP
1.127 +
1.128 + ; initialise the stack frame pointer
1.129 +
1.130 + txa
1.131 + sta SP
1.132 + lda #$01 ; $01xx
1.133 + sta SPH
1.134 +
1.135 + ; adjust the "user space" stack pointer to be compatible with the PC stack
1.136 +
1.137 + .invoke sub16 3, USER
1.138 +
1.139 + ; copy the PC
1.140 +
1.141 + ldy #3
1.142 + .invoke mov8_refs USER, SP
1.143 + iny
1.144 + .invoke mov8_refs USER, SP
1.145 +
1.146 + ; update the "user space" stack pointer
1.147 +
1.148 + .invoke add16 5, USER
1.149 +
1.150 + ; restore zero-page locations used
1.151 +
1.152 + .invoke pull16 SP
1.153 +
1.154 + ; return to the stored PC
1.155 +
1.156 + pla
1.157 + tay ; stack -> Y
1.158 + pla
1.159 + tax ; stack -> X
1.160 + pla ; stack -> A
1.161 + rts
1.162 +
1.163 +
1.164 +
1.165 ; install the interrupt handler address in IRQ1V
1.166 ;
1.167 ; affects: A
1.168 @@ -134,32 +268,34 @@
1.169
1.170 .invoke mov16 current_task, CURRENT
1.171
1.172 + ; store the user stack for the task
1.173 +
1.174 + .invoke mov16_to_ref USER, CURRENT
1.175 +
1.176 ldy #5 ; offset of MSB (Y, X, A, F, LSB, MSB)
1.177 - lda (SP), y
1.178 - sta (CURRENT), y
1.179 + .invoke mov8_refs SP, CURRENT
1.180 dey
1.181 - lda (SP), y
1.182 - sta (CURRENT), y
1.183 + .invoke mov8_refs SP, CURRENT
1.184 dey
1.185 - lda (SP), y
1.186 - sta (CURRENT), y
1.187 + .invoke mov8_refs SP, CURRENT
1.188
1.189 ; load flags, PC from next task structure
1.190
1.191 - lda (NEXT), y
1.192 - sta (SP), y
1.193 + .invoke mov8_refs NEXT, SP
1.194 iny
1.195 - lda (NEXT), y
1.196 - sta (SP), y
1.197 + .invoke mov8_refs NEXT, SP
1.198 iny
1.199 - lda (NEXT), y
1.200 - sta (SP), y
1.201 + .invoke mov8_refs NEXT, SP
1.202 iny
1.203
1.204 ; make the next task the current one
1.205
1.206 .invoke mov16 NEXT, current_task
1.207
1.208 + ; set the user stack for the task
1.209 +
1.210 + .invoke mov16_from_ref NEXT, USER
1.211 +
1.212 exit_handler:
1.213
1.214 ; restore zero-page locations used in the handler
1.215 @@ -202,9 +338,8 @@
1.216
1.217 ; add a new task to the table
1.218 ;
1.219 -; $76, $77: location of task structure
1.220 +; ARG0, ARG0H: location of task structure
1.221 ; affects: A, Y
1.222 -; returns: A = 0 (success); A = 1 (failure)
1.223
1.224 new_task:
1.225
1.226 @@ -230,19 +365,17 @@
1.227 ; copy the task structure location to the table
1.228
1.229 sei
1.230 - lda $77
1.231 + lda ARG0H
1.232 sta tasks, y
1.233 dey
1.234 - lda $76
1.235 + lda ARG0
1.236 sta tasks, y
1.237 cli
1.238
1.239 - lda #0
1.240 - rts
1.241 + .invoke return
1.242
1.243 no_new_task:
1.244 - lda #1
1.245 - rts
1.246 + .invoke return
1.247
1.248
1.249
1.250 @@ -262,14 +395,14 @@
1.251 iny
1.252 sta tasks, y
1.253 cli
1.254 - rts
1.255 + .invoke return
1.256 +
1.257
1.258
1.259 ; example tasks
1.260
1.261 first_task:
1.262 - .byte 0 ; currently unused
1.263 - .byte 0 ; currently unused
1.264 + .word 0 ; user stack pointer
1.265 .byte 0 ; currently unused
1.266 .byte 0 ; saved flags
1.267 .word first_task_start ; saved PC
1.268 @@ -280,8 +413,7 @@
1.269
1.270
1.271 second_task:
1.272 - .byte 0 ; currently unused
1.273 - .byte 0 ; currently unused
1.274 + .word 0 ; user stack pointer
1.275 .byte 0 ; currently unused
1.276 .byte 0 ; saved flags
1.277 .word second_task_start ; saved PC
1.278 @@ -292,8 +424,7 @@
1.279
1.280
1.281 third_task:
1.282 - .byte 0 ; currently unused
1.283 - .byte 0 ; currently unused
1.284 + .word third_task_stack_base ; user stack pointer
1.285 .byte 0 ; currently unused
1.286 .byte 0 ; saved flags
1.287 .word third_task_start ; saved PC
1.288 @@ -308,10 +439,18 @@
1.289 cmp #$ff
1.290 bne _continue
1.291 txa
1.292 - jsr remove_task
1.293 + .invoke call remove_task
1.294 inx
1.295 _continue:
1.296 .invoke add16 1, $7010
1.297 jmp _loop
1.298 +third_task_stack:
1.299 + .word 0
1.300 + .word 0
1.301 + .word 0
1.302 + .word 0
1.303 + .word 0
1.304 + .word 0
1.305 +third_task_stack_base:
1.306
1.307 ; vim: tabstop=4 expandtab shiftwidth=4