.text .global _sched_handler .type _sched_handler, @function .extern _sched_timer_id .extern _sched_timer_address .extern _sched_schedule .align 2 /* ** @note ** We can use only r0 - r7 register because ** we SHOULD not modify the current process context. */ _sched_handler: /* ** Stop scheduler timer and clear interrupt flags */ stop_clear_sched_timer: ! Clear scheduler timer interrupt mov.l .sched_timer_address, r0 ! get precalculated scheduler timer address mov.l .timer_unf_field, r1 ! get TIMER.TCR.UNF byte field mov.l @r0, r0 ! get scheduler timer TCR register mov.w @r0, r2 ! get scheduler timer TCR register not r1, r1 ! get interrupt flags bit mask (to remove) and r1, r2 ! clear timer interrupt flags mov.w r2, @r0 ! update timer TCR ! Stop scheduler timer mov.l .sched_timer_tstr_bit, r0 ! get precalculated scheduler timer ID mov.l .timer_tstr_register, r1 ! get TMU0.TSTR base address mov.l @r0, r0 ! get scheduler timer ID mov.b @r1, r2 ! get TMU0.TSTR data not r0, r0 ! get TSTR scheduler timer ID mask (to remove) and r0, r2 ! stop scheduler timer mov.b r2, @r1 ! update TMU0.TSTR #ifdef __SCHED_DEBUG__ sts.l pr, @-r15 ! save pr register mov #0, r4 ! save r4 register (current context) mov #0, r5 ! save r5 register (next context) mov.l .sched_debug, r0 ! get sched_debug() absraction jsr @r0 ! call abstraction nop ! (db) nop lds.l @r15+, pr ! restore pr register bra restart_sched_timer nop #endif /* ** Get current and next context */ get_contexts: ! prologue mov.l r9, @-r15 ! save r9 register mov.l r8, @-r15 ! save r8 register sts.l pr, @-r15 ! save pr register ! Create to context_common_t **ptr add #-4, r15 ! create first context pointer mov r15, r8 ! save first context pointer add #-4, r15 ! create second context pointer mov r15, r9 ! save second context pointer add #-4, r15 ! create context pointer mov.l r15, @r8 ! save context pointer add #-4, r15 ! create context pointer mov.l r15, @r9 ! save context pointer ! call high level abstraction mov r8, r4 ! send current contexts pointer mov r9, r5 ! send next context pointer mov.l .sched_schedule, r0 ! get sched_scheduler() abstraction address jsr @r0 ! call sched_schedule() abstract nop ! (db) nop ! Restore stack and register (epilogue) mov.l @r8, r4 ! save current context mov.l @r9, r5 ! save next context add #16, r15 ! restore stack lds.l @r15+, pr ! restore pr register mov.l @r15+, r8 ! restore r8 register mov.l @r15+, r9 ! restore r9 register ! Check context error tst r0, r0 ! check if returned value == 0... bt debug ! if yes, jump at bra restart_sched_timer ! jump at nop ! (db) nop /* ** Debug part, used to debug the contexts */ debug: #ifdef __SCHED_DEBUG__ sts.l pr, @-r15 ! save pr register mov.l r4, @-r15 ! save r4 register (current context) mov.l r5, @-r15 ! save r5 register (next context) mov.l .sched_debug, r0 ! get sched_debug() absraction jsr @r0 ! call abstraction nop ! (db) nop mov.l @r15+, r5 ! restore r5 register mov.l @r15+, r4 ! restore r4 register lds.l @r15+, pr ! restore pr register #endif /* ** Context switch */ save_current_context: ! Check current process ! @note: current process can be NULL ! tst r4, r4 ! if current task == NULL... bt next_context_load ! ...if yes, jump at add #88, r4 ! get &process->context (end) ! save current context sts.l pr, @-r4 ! get pr regsiter stc.l spc, @-r4 ! get spc regsiter stc.l ssr, @-r4 ! get ssr regsiter sts.l mach, @-r4 ! get mach regsiter sts.l macl, @-r4 ! get macl regsiter stc.l gbr, @-r4 ! get gbr regsiter mov.l r15, @-r4 ! get r15 register mov.l r14, @-r4 ! get r14 regsiter mov.l r13, @-r4 ! get r13 regsiter mov.l r12, @-r4 ! get r12 regsiter mov.l r11, @-r4 ! get r11 regsiter mov.l r10, @-r4 ! get r10 regsiter mov.l r9, @-r4 ! get r9 regsiter mov.l r8, @-r4 ! get r8 regsiter stc.l R7_BANK, @-r4 ! get "process" r7 regsiter stc.l R6_BANK, @-r4 ! get "process" r6 regsiter stc.l R5_BANK, @-r4 ! get "process" r5 regsiter stc.l R4_BANK, @-r4 ! get "process" r4 regsiter stc.l R3_BANK, @-r4 ! get "process" r3 regsiter stc.l R2_BANK, @-r4 ! get "process" r2 regsiter stc.l R1_BANK, @-r4 ! get "process" r1 regsiter stc.l R0_BANK, @-r4 ! get "process" r0 regsiter next_context_load: ! Load next process ! @note: next process can not be NULL ! ldc.l @r5+, R0_BANK ! set "process" r0 regsiter ldc.l @r5+, R1_BANK ! set "process" r1 regsiter ldc.l @r5+, R2_BANK ! set "process" r2 regsiter ldc.l @r5+, R3_BANK ! set "process" r3 regsiter ldc.l @r5+, R4_BANK ! set "process" r4 regsiter ldc.l @r5+, R5_BANK ! set "process" r5 regsiter ldc.l @r5+, R6_BANK ! set "process" r6 regsiter ldc.l @r5+, R7_BANK ! set "process" r7 regsiter mov.l @r5+, r8 ! set r8 regsiter mov.l @r5+, r9 ! set r9 regsiter mov.l @r5+, r10 ! set r10 regsiter mov.l @r5+, r11 ! set r11 regsiter mov.l @r5+, r12 ! set r12 regsiter mov.l @r5+, r13 ! set r13 regsiter mov.l @r5+, r14 ! set r14 regsiter mov.l @r5+, r15 ! set r15 register ldc.l @r5+, gbr ! set gbr regsiter lds.l @r5+, macl ! set macl regsiter lds.l @r5+, mach ! set mach regsiter ldc.l @r5+, ssr ! set ssr regsiter ldc.l @r5+, spc ! set spc regsiter lds.l @r5+, pr ! set pr regsiter /* ** Restart timer */ restart_sched_timer: mov.l .sched_timer_tstr_bit, r0 ! get precalculated scheduler timer ID mov.l .timer_tstr_register, r1 ! get TMU0.TSTR base address mov.l @r0, r0 ! get scheduler timer ID mov.b @r1, r2 ! get TMU0.TSTR data or r0, r2 ! start scheduler timer mov.b r2, @r1 ! update TMU0.TSTR /* ** Process switch */ process_switch: rte ! use RTE to switch process nop ! (db) nop .align 4 .sched_timer_tstr_bit: .long _sched_timer_tstr_bit .sched_timer_address: .long _sched_timer_address .sched_schedule: .long _sched_schedule .timer_tstr_register: .long 0xa4490004 .timer_unf_field: .long 0x00000100 #ifndef __SCHED_DEBUG__ .sched_debug: .long _sched_debug #endif .end