|
| 1 | +/* This file is part of the Diamond cothread library. |
| 2 | + * |
| 3 | + * Copyright (C) 2010-2012 Michael Abbott, Diamond Light Source Ltd. |
| 4 | + * |
| 5 | + * The Diamond cothread library is free software; you can redistribute it |
| 6 | + * and/or modify it under the terms of the GNU General Public License as |
| 7 | + * published by the Free Software Foundation; either version 2 of the License, |
| 8 | + * or (at your option) any later version. |
| 9 | + * |
| 10 | + * The Diamond cothread library is distributed in the hope that it will be |
| 11 | + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
| 13 | + * Public License for more details. |
| 14 | + * |
| 15 | + * You should have received a copy of the GNU General Public License along |
| 16 | + * with this program; if not, write to the Free Software Foundation, Inc., 51 |
| 17 | + * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | + * |
| 19 | + * Contact: |
| 20 | + * Dr. Michael Abbott, |
| 21 | + * Diamond Light Source Ltd, |
| 22 | + * Diamond House, |
| 23 | + * Chilton, |
| 24 | + * Didcot, |
| 25 | + * Oxfordshire, |
| 26 | + * OX11 0DE |
| 27 | + * michael.abbott@diamond.ac.uk |
| 28 | + */ |
| 29 | + |
| 30 | +// Coroutine frame switching for ARMv8 64 bits |
| 31 | + |
| 32 | +#ifdef __ARM_NEON |
| 33 | +#define IF_NEON(code) code |
| 34 | +#else |
| 35 | +#define IF_NEON(code) |
| 36 | +#endif |
| 37 | + |
| 38 | +__asm__( |
| 39 | +" .text\n" |
| 40 | + |
| 41 | +// void * switch_frame(frame_t *old_frame, frame_t new_frame, void *arg) |
| 42 | +// Arguments on entry: |
| 43 | +// x0 address of frame to be saved |
| 44 | +// x1 frame to be loaded |
| 45 | +// x2 Context argument to pass through |
| 46 | + |
| 47 | +FNAME(switch_frame) |
| 48 | +" stp x19, x20, [sp, #-16]!\n" |
| 49 | +" stp x21, x22, [sp, #-16]!\n" |
| 50 | +" stp x23, x24, [sp, #-16]!\n" |
| 51 | +" stp x25, x26, [sp, #-16]!\n" |
| 52 | +" stp x27, x28, [sp, #-16]!\n" |
| 53 | +" stp fp, lr, [sp, #-16]!\n" |
| 54 | +IF_NEON( |
| 55 | +" stp d8, d9, [sp, #-16]!\n" |
| 56 | +" stp d10, d11, [sp, #-16]!\n" |
| 57 | +" stp d12, d13, [sp, #-16]!\n" |
| 58 | +" stp d14, d15, [sp, #-16]!\n" |
| 59 | +) |
| 60 | +" mov ip0, sp\n" |
| 61 | +" str ip0, [x0]\n" |
| 62 | +" mov sp, x1\n" |
| 63 | +" mov x0, x2\n" |
| 64 | +IF_NEON( |
| 65 | +" ldp d14, d15, [sp], #16\n" |
| 66 | +" ldp d12, d13, [sp], #16\n" |
| 67 | +" ldp d10, d11, [sp], #16\n" |
| 68 | +" ldp d8, d9, [sp], #16\n" |
| 69 | +) |
| 70 | +" ldp fp, lr, [sp], #16\n" |
| 71 | +" ldp x27, x28, [sp], #16\n" |
| 72 | +" ldp x25, x26, [sp], #16\n" |
| 73 | +" ldp x23, x24, [sp], #16\n" |
| 74 | +" ldp x21, x22, [sp], #16\n" |
| 75 | +" ldp x19, x20, [sp], #16\n" |
| 76 | +" br lr\n" |
| 77 | +FSIZE(switch_frame) |
| 78 | + |
| 79 | + |
| 80 | +// frame_t create_frame(void *stack_base, frame_action_t action, void *context) |
| 81 | +// Arguments on entry: |
| 82 | +// x0 initial base of stack |
| 83 | +// x1 action routine |
| 84 | +// x2 context argument to action |
| 85 | +FNAME(create_frame) |
| 86 | +" stp x1, x2, [x0, #-16]!\n" |
| 87 | +" mov ip0, lr\n" // Save LR so can use same STP slot |
| 88 | +" ldr lr, =action_entry\n" |
| 89 | +" stp x19, x20, [x0, #-16]!\n" |
| 90 | +" stp x21, x22, [x0, #-16]!\n" |
| 91 | +" stp x23, x24, [x0, #-16]!\n" |
| 92 | +" stp x25, x26, [x0, #-16]!\n" |
| 93 | +" stp x27, x28, [x0, #-16]!\n" |
| 94 | +" stp fp, lr, [x0, #-16]!\n" |
| 95 | +IF_NEON( |
| 96 | +" stp d8, d9, [x0, #-16]!\n" |
| 97 | +" stp d10, d11, [x0, #-16]!\n" |
| 98 | +" stp d12, d13, [x0, #-16]!\n" |
| 99 | +" stp d14, d15, [x0, #-16]!\n" |
| 100 | +) |
| 101 | +" br ip0\n" |
| 102 | + |
| 103 | +"action_entry:\n" |
| 104 | + // Receive control after first switch to new frame. Top of stack has |
| 105 | + // the saved context and routine to call, switch argument is in r0. |
| 106 | +" ldp x2, x3, [sp], #16\n" // x2 <- action routine, x3 <- context |
| 107 | +" mov x1, x3\n" |
| 108 | +" mov lr, #0\n" // Ensure no return from action |
| 109 | +" br x2\n" |
| 110 | +FSIZE(create_frame) |
| 111 | +); |
0 commit comments