|
| 1 | +static void *slp_switch(void *(*save_state)(void*, void*), |
| 2 | + void *(*restore_state)(void*, void*), |
| 3 | + void *extra) |
| 4 | +{ |
| 5 | + void *result; |
| 6 | + __asm__ volatile ( |
| 7 | + "daddiu $sp, $sp, -0x50\n" |
| 8 | + "sd $s0, 0x0($sp)\n" /* push the registers specified as caller-save */ |
| 9 | + "sd $s1, 0x8($sp)\n" |
| 10 | + "sd $s2, 0x10($sp)\n" |
| 11 | + "sd $s3, 0x18($sp)\n" |
| 12 | + "sd $s4, 0x20($sp)\n" |
| 13 | + "sd $s5, 0x28($sp)\n" |
| 14 | + "sd $s6, 0x30($sp)\n" |
| 15 | + "sd $s7, 0x38($sp)\n" |
| 16 | + "sd $fp, 0x40($sp)\n" |
| 17 | + "sd $ra, 0x48($sp)\n" |
| 18 | + |
| 19 | + "move $s0, %[rstate]\n" /* save 'restore_state' for later */ |
| 20 | + "move $s1, %[extra]\n" /* save 'extra' for later */ |
| 21 | + |
| 22 | + "move $a1, %[extra]\n"/* arg 2: extra */ |
| 23 | + "move $a0, $sp\n" /* arg 1: current (old) stack pointer */ |
| 24 | + |
| 25 | + "move $t9, %[sstate]\n" |
| 26 | + "jalr $t9\n" /* call save_state() */ |
| 27 | + |
| 28 | + "beqz $v0, 0f\n" /* skip the rest if the return value is null */ |
| 29 | + |
| 30 | + "move $sp, $v0\n" /* change the stack pointer */ |
| 31 | + |
| 32 | + /* From now on, the stack pointer is modified, but the content of the |
| 33 | + stack is not restored yet. It contains only garbage here. */ |
| 34 | + |
| 35 | + "move $a1, $s1\n" /* arg 2: extra */ |
| 36 | + "move $a0, $v0\n" /* arg 1: current (new) stack pointer */ |
| 37 | + "move $t9, $s0\n" |
| 38 | + "jalr $t9\n" /* call restore_state() */ |
| 39 | + |
| 40 | + /* The stack's content is now restored. */ |
| 41 | + |
| 42 | + "0:\n" |
| 43 | + "move %[result], $v0\n" |
| 44 | + "ld $s0, 0x0($sp)\n" |
| 45 | + "ld $s1, 0x8($sp)\n" |
| 46 | + "ld $s2, 0x10($sp)\n" |
| 47 | + "ld $s3, 0x18($sp)\n" |
| 48 | + "ld $s4, 0x20($sp)\n" |
| 49 | + "ld $s5, 0x28($sp)\n" |
| 50 | + "ld $s6, 0x30($sp)\n" |
| 51 | + "ld $s7, 0x38($sp)\n" |
| 52 | + "ld $fp, 0x40($sp)\n" |
| 53 | + "ld $ra, 0x48($sp)\n" |
| 54 | + "daddiu $sp, $sp, 0x50\n" |
| 55 | + |
| 56 | + : [result]"=&r"(result) |
| 57 | + : [sstate]"r"(save_state), |
| 58 | + [rstate]"r"(restore_state), |
| 59 | + [extra]"r"(extra) |
| 60 | + : "memory", "v0", "a0", "a1", "t9" |
| 61 | + ); |
| 62 | + return result; |
| 63 | +} |
0 commit comments