.file "context-switch.s" .text .align 2 .global kerent .type kerent, %function kerent: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 1, uses_anonymous_args = 0 @ switch to system mode msr cpsr_c, #0xdf @ push regs onto users stack stmfd sp!, {r1-r12,r14} @ save spsr to r2 mrs r2, spsr @ copy sp to r1 for later saving on to td mov r1, sp @ switch to svc mode msr cpsr_c, #0xd3 @ create vague register to set td->RetVal, it doesn't matter the val mov r3, #0 @ mov args from r0 to r4 mov r4, r0 @ mov sp from r1 to r0 mov r0, r1 @ mov lr_svc to r1 mov r1, lr @ load Task from kernel sp into r5 ldmfd sp!, {r5} @ store sp_usr(r0), lr_svc(r1), spsr(r2),retval(r3),args(r4) onto Task @ first subtract td value add r5, r5, #20 @ then store stmfd r5, {r0-r4} @ get swi number into r0 ldr r0, [lr, #-4] @ mask off high bits bic r0, r0, #0xff000000 /* mov r0, #1 mov r1, #6 bl bwputr(PLT) */ @ pop kernels stack ldmfd sp!, {r1-r12,pc} .size kerent, .-kerent @================================================================================== .align 2 .global kerxit .type kerxit, %function kerxit: @ this is equi to activate, an entry point in the kernel to which it goes @ when its ready to restart the active task @ args = 0, pretend = 0, frame = 8 @ frame_needed = 1, uses_anonymous_args = 0 @ r0 = Task @ push kernel's registers, Task saved on kernels stack stmfd sp!, {r0-r12, r14} @ r0 is Task, get sp_user, lr, cpsr_user, retval ldmfd r0, {r0-r3} @ get lr(int r1) into r14(lr_svc) mov lr, r1 @ load user's cpsr(in r2) to spsr msr spsr, r2 @ mov sp_usr from r0 to r2 mov r2, r0 @ return value from r3 into r0 mov r0, r3 @ switch to system mode msr cpsr_c, #0xdf @ set user sp mov sp, r2 @ restore user's registers ldmfd sp!, {r1-r12, r14} @ switch back to svc mode msr cpsr_c, #0xd3 @ go to usr program movs pc, lr .size kerxit, .-kerxit .ident "GCC: (GNU) 4.0.2"