123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- /* author: Shawn Anastasio */
- #define LIBCO_C
- #include "libco.h"
- #include "settings.h"
- #include <stdint.h>
- #ifdef __cplusplus
- extern "C" {
- #endif
- struct ppc64_context {
- /* GPRs */
- uint64_t gprs[32];
- uint64_t lr;
- uint64_t ccr;
- /* FPRs */
- uint64_t fprs[32];
- #ifdef __ALTIVEC__
- /* Altivec (VMX) */
- uint64_t vmx[12 * 2];
- uint32_t vrsave;
- #endif
- };
- static thread_local struct ppc64_context* co_active_handle = 0;
- #define MAX(x, y) ((x) > (y) ? (x) : (y))
- #define ALIGN(p, x) ((void*)((uintptr_t)(p) & ~((x) - 1)))
- #define MIN_STACK 0x10000lu
- #define MIN_STACK_FRAME 0x20lu
- #define STACK_ALIGN 0x10lu
- void swap_context(struct ppc64_context* read, struct ppc64_context* write);
- __asm__(
- ".text\n"
- ".align 4\n"
- ".type swap_context @function\n"
- "swap_context:\n"
- ".cfi_startproc\n"
- /* save GPRs */
- "std 1, 8(4)\n"
- "std 2, 16(4)\n"
- "std 12, 96(4)\n"
- "std 13, 104(4)\n"
- "std 14, 112(4)\n"
- "std 15, 120(4)\n"
- "std 16, 128(4)\n"
- "std 17, 136(4)\n"
- "std 18, 144(4)\n"
- "std 19, 152(4)\n"
- "std 20, 160(4)\n"
- "std 21, 168(4)\n"
- "std 22, 176(4)\n"
- "std 23, 184(4)\n"
- "std 24, 192(4)\n"
- "std 25, 200(4)\n"
- "std 26, 208(4)\n"
- "std 27, 216(4)\n"
- "std 28, 224(4)\n"
- "std 29, 232(4)\n"
- "std 30, 240(4)\n"
- "std 31, 248(4)\n"
- /* save LR */
- "mflr 5\n"
- "std 5, 256(4)\n"
- /* save CCR */
- "mfcr 5\n"
- "std 5, 264(4)\n"
- /* save FPRs */
- "stfd 14, 384(4)\n"
- "stfd 15, 392(4)\n"
- "stfd 16, 400(4)\n"
- "stfd 17, 408(4)\n"
- "stfd 18, 416(4)\n"
- "stfd 19, 424(4)\n"
- "stfd 20, 432(4)\n"
- "stfd 21, 440(4)\n"
- "stfd 22, 448(4)\n"
- "stfd 23, 456(4)\n"
- "stfd 24, 464(4)\n"
- "stfd 25, 472(4)\n"
- "stfd 26, 480(4)\n"
- "stfd 27, 488(4)\n"
- "stfd 28, 496(4)\n"
- "stfd 29, 504(4)\n"
- "stfd 30, 512(4)\n"
- "stfd 31, 520(4)\n"
- #ifdef __ALTIVEC__
- /* save VMX */
- "li 5, 528\n"
- "stvxl 20, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 21, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 22, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 23, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 24, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 25, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 26, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 27, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 28, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 29, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 30, 4, 5\n"
- "addi 5, 5, 16\n"
- "stvxl 31, 4, 5\n"
- "addi 5, 5, 16\n"
- /* save VRSAVE */
- "mfvrsave 5\n"
- "stw 5, 736(4)\n"
- #endif
- /* restore GPRs */
- "ld 1, 8(3)\n"
- "ld 2, 16(3)\n"
- "ld 12, 96(3)\n"
- "ld 13, 104(3)\n"
- "ld 14, 112(3)\n"
- "ld 15, 120(3)\n"
- "ld 16, 128(3)\n"
- "ld 17, 136(3)\n"
- "ld 18, 144(3)\n"
- "ld 19, 152(3)\n"
- "ld 20, 160(3)\n"
- "ld 21, 168(3)\n"
- "ld 22, 176(3)\n"
- "ld 23, 184(3)\n"
- "ld 24, 192(3)\n"
- "ld 25, 200(3)\n"
- "ld 26, 208(3)\n"
- "ld 27, 216(3)\n"
- "ld 28, 224(3)\n"
- "ld 29, 232(3)\n"
- "ld 30, 240(3)\n"
- "ld 31, 248(3)\n"
- /* restore LR */
- "ld 5, 256(3)\n"
- "mtlr 5\n"
- /* restore CCR */
- "ld 5, 264(3)\n"
- "mtcr 5\n"
- /* restore FPRs */
- "lfd 14, 384(3)\n"
- "lfd 15, 392(3)\n"
- "lfd 16, 400(3)\n"
- "lfd 17, 408(3)\n"
- "lfd 18, 416(3)\n"
- "lfd 19, 424(3)\n"
- "lfd 20, 432(3)\n"
- "lfd 21, 440(3)\n"
- "lfd 22, 448(3)\n"
- "lfd 23, 456(3)\n"
- "lfd 24, 464(3)\n"
- "lfd 25, 472(3)\n"
- "lfd 26, 480(3)\n"
- "lfd 27, 488(3)\n"
- "lfd 28, 496(3)\n"
- "lfd 29, 504(3)\n"
- "lfd 30, 512(3)\n"
- "lfd 31, 520(3)\n"
- #ifdef __ALTIVEC__
- /* restore VMX */
- "li 5, 528\n"
- "lvxl 20, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 21, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 22, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 23, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 24, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 25, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 26, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 27, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 28, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 29, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 30, 3, 5\n"
- "addi 5, 5, 16\n"
- "lvxl 31, 3, 5\n"
- "addi 5, 5, 16\n"
- /* restore VRSAVE */
- "lwz 5, 720(3)\n"
- "mtvrsave 5\n"
- #endif
- /* branch to LR */
- "blr\n"
- ".cfi_endproc\n"
- ".size swap_context, .-swap_context\n"
- );
- cothread_t co_active() {
- if(!co_active_handle) {
- co_active_handle = (struct ppc64_context*)LIBCO_MALLOC(MIN_STACK + sizeof(struct ppc64_context));
- }
- return (cothread_t)co_active_handle;
- }
- cothread_t co_derive(void* memory, unsigned int size, void (*coentry)(void)) {
- uint8_t* sp;
- struct ppc64_context* context = (struct ppc64_context*)memory;
- /* save current context into new context to initialize it */
- swap_context(context, context);
- /* align stack */
- sp = (uint8_t*)memory + size - STACK_ALIGN;
- sp = (uint8_t*)ALIGN(sp, STACK_ALIGN);
- /* write 0 for initial backchain */
- *(uint64_t*)sp = 0;
- /* create new frame with backchain */
- sp -= MIN_STACK_FRAME;
- *(uint64_t*)sp = (uint64_t)(sp + MIN_STACK_FRAME);
- /* update context with new stack (r1) and entrypoint (r12, lr) */
- context->gprs[ 1] = (uint64_t)sp;
- context->gprs[12] = (uint64_t)coentry;
- context->lr = (uint64_t)coentry;
- return (cothread_t)memory;
- }
- cothread_t co_create(unsigned int size, void (*coentry)(void)) {
- void* memory = LIBCO_MALLOC(size);
- if(!memory) return (cothread_t)0;
- return co_derive(memory, size, coentry);
- }
- void co_delete(cothread_t handle) {
- LIBCO_FREE(handle);
- }
- void co_switch(cothread_t to) {
- struct ppc64_context* from = co_active_handle;
- co_active_handle = (struct ppc64_context*)to;
- swap_context((struct ppc64_context*)to, from);
- }
- int co_serializable() {
- return 1;
- }
- #ifdef __cplusplus
- }
- #endif
|