diff --git a/libco/libco.S b/libco/libco.S new file mode 100644 index 0000000..9a349fe --- /dev/null +++ b/libco/libco.S @@ -0,0 +1,128 @@ +@ vim: set ft=armv5: + +.cpu cortex-m0 +.thumb + +/*.section .bss.co_active_buffer, "aw", %nobits +.type co_active_buffer, %object +.size co_active_buffer, 4*64 +co_active_buffer: + .space 4*64 + +.section .bss.co_active_handle, "aw", %nobits +.type co_active_handle, %object +.size co_active_handle, 4 +co_active_handle: + .space 4*/ + +.extern co_active_handle +.extern co_active_buffer + +.section .text.co_active, "ax", %progbits +.type co_active, %function +.thumb_func +.global co_active +co_active:@() + ldr r1, =co_active_handle + ldr r0, [r1] + cmp r0, #0 + bne 1f + + ldr r0, =co_active_buffer + str r0, [r1] + +1: bx lr + + .pool + +.section .text.co_switch, "ax", %progbits +.type co_switch, %function +.thumb_func +.global co_switch +co_switch:@(cothread_t handle r0) + @ co_previous_handle(r1) = co_active_handle + @ co_active_handle = handle(r0) + ldr r2, =co_active_handle + ldr r1, [r2] + str r0, [r2] + + @ co_swap() + + @ NOTE: we're assuming that the hw divider's state persistance won't be + @ used + + @ original ARM version: + @stmia r1!, {r4-r11,sp,lr} + @ldmia r0!, {r4-r11,sp,pc} + @bx lr + + stmia r1!, {r4-r7} + mov r2, r8 + mov r3, r9 + mov r4, r10 + mov r5, r11 + mov r6, r12 + mov r7, sp + stmia r1!, {r2-r7} + mov r2, lr + stmia r1!, {r2} + + @ TODO: this could be done better, but oh well + ldr r2, [r0, #0x10] @ r8 + ldr r3, [r0, #0x14] @ r9 + ldr r4, [r0, #0x18] @ r10 + ldr r5, [r0, #0x1c] @ r11 + ldr r6, [r0, #0x20] @ r12 + ldr r7, [r0, #0x24] @ sp + mov r8, r2 + mov r9, r3 + mov r10, r4 + mov r11, r5 + mov r12, r6 + mov sp, r7 + + ldmia r0!, {r4-r7} + + ldr r2, [r0, #(0x28-0x10)] @ pc + mov pc, r2 + + bx lr + + .pool + +.section .text.co_derive, "ax", %progbits +.type co_derive, %function +.thumb_func +.global co_derive +co_derive:@(void* memory r0, unsigned int size r1, void(*entrypoint)(void) r2) + push {r4} + + @ if (!co_active_handle) co_active_handle = &co_active_buffer + ldr r3, =co_active_handle + ldr r4, [r3] + cmp r4, #0 + bne 1f + + ldr r4, =co_active_buffer + str r4, [r3] + + @ if (!memory) return 0; +1: cmp r0, #0 + beq .Lret + + @ offset(r3) = size(r1) & ~15 + mov r3, r1 + mov r4, #0xf + bic r3, r4 @ doesn't want to do an immediate, sigh... + @ p(r3) = handle(r0) + offset(r3) + add r3, r0 + @ initialize stack, entrypoint + str r3, [r0, #( 9*4)] + str r2, [r0, #(10*4)] + +.Lret: + pop {r4} + bx lr + + .pool + diff --git a/libco/libco.h b/libco/libco.h new file mode 100644 index 0000000..bdf5154 --- /dev/null +++ b/libco/libco.h @@ -0,0 +1,15 @@ + +/* derived from libco v20, by byuu (ISC) */ + +#ifndef LIBCO_H_ +#define LIBCO_H_ + +typedef void* cothread_t; + +cothread_t co_active(void); +cothread_t co_derive(void* memory, unsigned int heapsize, void (*coentry)(void)); +void co_switch(cothread_t); +int co_serializable(void); + +#endif + diff --git a/thread.h b/thread.h new file mode 100644 index 0000000..efa203e --- /dev/null +++ b/thread.h @@ -0,0 +1,8 @@ + +#ifndef THREAD_H_ +#define THREAD_H_ + +void thread_yield(void); + +#endif +