No Changes

Dependencies:   BLE_API mbed-dev-bin nRF51822

Dependents:   microbit

Fork of microbit-dal by Lancaster University

Committer:
Asimov
Date:
Fri Jan 13 21:14:06 2017 +0000
Revision:
75:ae9a17da71af
Parent:
14:6dcf65f61a11
No Changes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
LancasterUniversity 14:6dcf65f61a11 1 ; The MIT License (MIT)
LancasterUniversity 14:6dcf65f61a11 2
LancasterUniversity 14:6dcf65f61a11 3 ; Copyright (c) 2016 British Broadcasting Corporation.
LancasterUniversity 14:6dcf65f61a11 4 ; This software is provided by Lancaster University by arrangement with the BBC.
LancasterUniversity 14:6dcf65f61a11 5
LancasterUniversity 14:6dcf65f61a11 6 ; Permission is hereby granted, free of charge, to any person obtaining a
LancasterUniversity 14:6dcf65f61a11 7 ; copy of this software and associated documentation files (the "Software"),
LancasterUniversity 14:6dcf65f61a11 8 ; to deal in the Software without restriction, including without limitation
LancasterUniversity 14:6dcf65f61a11 9 ; the rights to use, copy, modify, merge, publish, distribute, sublicense,
LancasterUniversity 14:6dcf65f61a11 10 ; and/or sell copies of the Software, and to permit persons to whom the
LancasterUniversity 14:6dcf65f61a11 11 ; Software is furnished to do so, subject to the following conditions:
LancasterUniversity 14:6dcf65f61a11 12
LancasterUniversity 14:6dcf65f61a11 13 ; The above copyright notice and this permission notice shall be included in
LancasterUniversity 14:6dcf65f61a11 14 ; all copies or substantial portions of the Software.
LancasterUniversity 14:6dcf65f61a11 15
LancasterUniversity 14:6dcf65f61a11 16 ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
LancasterUniversity 14:6dcf65f61a11 17 ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
LancasterUniversity 14:6dcf65f61a11 18 ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
LancasterUniversity 14:6dcf65f61a11 19 ; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LancasterUniversity 14:6dcf65f61a11 20 ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
LancasterUniversity 14:6dcf65f61a11 21 ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
LancasterUniversity 14:6dcf65f61a11 22 ; DEALINGS IN THE SOFTWARE.
LancasterUniversity 14:6dcf65f61a11 23
LancasterUniversity 14:6dcf65f61a11 24 AREA asm_func, CODE, READONLY
LancasterUniversity 14:6dcf65f61a11 25
LancasterUniversity 14:6dcf65f61a11 26 ; Export our context switching subroutine as a C function for use in mbed
LancasterUniversity 14:6dcf65f61a11 27 EXPORT swap_context
LancasterUniversity 14:6dcf65f61a11 28 EXPORT save_context
LancasterUniversity 14:6dcf65f61a11 29 EXPORT save_register_context
LancasterUniversity 14:6dcf65f61a11 30 EXPORT restore_register_context
LancasterUniversity 14:6dcf65f61a11 31
LancasterUniversity 14:6dcf65f61a11 32 ALIGN
LancasterUniversity 14:6dcf65f61a11 33
LancasterUniversity 14:6dcf65f61a11 34 ; R0 Contains a pointer to the TCB of the fibre being scheduled out.
LancasterUniversity 14:6dcf65f61a11 35 ; R1 Contains a pointer to the TCB of the fibre being scheduled in.
LancasterUniversity 14:6dcf65f61a11 36 ; R2 Contains a pointer to the base of the stack of the fibre being scheduled out.
LancasterUniversity 14:6dcf65f61a11 37 ; R3 Contains a pointer to the base of the stack of the fibre being scheduled in.
LancasterUniversity 14:6dcf65f61a11 38
LancasterUniversity 14:6dcf65f61a11 39 swap_context
LancasterUniversity 14:6dcf65f61a11 40
LancasterUniversity 14:6dcf65f61a11 41 ; Write our core registers into the TCB
LancasterUniversity 14:6dcf65f61a11 42 ; First, store the general registers
LancasterUniversity 14:6dcf65f61a11 43
LancasterUniversity 14:6dcf65f61a11 44 ; Skip this is we're given a NULL parameter for the TCB
LancasterUniversity 14:6dcf65f61a11 45 CMP R0, #0
LancasterUniversity 14:6dcf65f61a11 46 BEQ store_context_complete
LancasterUniversity 14:6dcf65f61a11 47
LancasterUniversity 14:6dcf65f61a11 48 STR R0, [R0,#0]
LancasterUniversity 14:6dcf65f61a11 49 STR R1, [R0,#4]
LancasterUniversity 14:6dcf65f61a11 50 STR R2, [R0,#8]
LancasterUniversity 14:6dcf65f61a11 51 STR R3, [R0,#12]
LancasterUniversity 14:6dcf65f61a11 52 STR R4, [R0,#16]
LancasterUniversity 14:6dcf65f61a11 53 STR R5, [R0,#20]
LancasterUniversity 14:6dcf65f61a11 54 STR R6, [R0,#24]
LancasterUniversity 14:6dcf65f61a11 55 STR R7, [R0,#28]
LancasterUniversity 14:6dcf65f61a11 56
LancasterUniversity 14:6dcf65f61a11 57 ; Now the high general purpose registers
LancasterUniversity 14:6dcf65f61a11 58 MOV R4, R8
LancasterUniversity 14:6dcf65f61a11 59 STR R4, [R0,#32]
LancasterUniversity 14:6dcf65f61a11 60 MOV R4, R9
LancasterUniversity 14:6dcf65f61a11 61 STR R4, [R0,#36]
LancasterUniversity 14:6dcf65f61a11 62 MOV R4, R10
LancasterUniversity 14:6dcf65f61a11 63 STR R4, [R0,#40]
LancasterUniversity 14:6dcf65f61a11 64 MOV R4, R11
LancasterUniversity 14:6dcf65f61a11 65 STR R4, [R0,#44]
LancasterUniversity 14:6dcf65f61a11 66 MOV R4, R12
LancasterUniversity 14:6dcf65f61a11 67 STR R4, [R0,#48]
LancasterUniversity 14:6dcf65f61a11 68
LancasterUniversity 14:6dcf65f61a11 69 ; Now the Stack and Link Register.
LancasterUniversity 14:6dcf65f61a11 70 ; As this context is only intended for use with a fiber scheduler,
LancasterUniversity 14:6dcf65f61a11 71 ; we don't need the PC.
LancasterUniversity 14:6dcf65f61a11 72 MOV R6, SP
LancasterUniversity 14:6dcf65f61a11 73 STR R6, [R0,#52]
LancasterUniversity 14:6dcf65f61a11 74 MOV R4, LR
LancasterUniversity 14:6dcf65f61a11 75 STR R4, [R0,#56]
LancasterUniversity 14:6dcf65f61a11 76
LancasterUniversity 14:6dcf65f61a11 77 store_context_complete
LancasterUniversity 14:6dcf65f61a11 78 ; Finally, Copy the stack. We do this to reduce RAM footprint, as stack is usually very small at the point
LancasterUniversity 14:6dcf65f61a11 79 ; of scheduling, but we need a lot of capacity for interrupt handling and other functions.
LancasterUniversity 14:6dcf65f61a11 80
LancasterUniversity 14:6dcf65f61a11 81 ; Skip this is we're given a NULL parameter for the stack.
LancasterUniversity 14:6dcf65f61a11 82 CMP R2, #0
LancasterUniversity 14:6dcf65f61a11 83 BEQ store_stack_complete
LancasterUniversity 14:6dcf65f61a11 84
LancasterUniversity 14:6dcf65f61a11 85 LDR R4, [R0,#60] ; Load R4 with the fiber's defined stack_base.
LancasterUniversity 14:6dcf65f61a11 86 store_stack
LancasterUniversity 14:6dcf65f61a11 87 SUBS R4, #4
LancasterUniversity 14:6dcf65f61a11 88 SUBS R2, #4
LancasterUniversity 14:6dcf65f61a11 89
LancasterUniversity 14:6dcf65f61a11 90 LDR R5, [R4]
LancasterUniversity 14:6dcf65f61a11 91 STR R5, [R2]
LancasterUniversity 14:6dcf65f61a11 92
LancasterUniversity 14:6dcf65f61a11 93 CMP R4, R6
LancasterUniversity 14:6dcf65f61a11 94 BNE store_stack
LancasterUniversity 14:6dcf65f61a11 95
LancasterUniversity 14:6dcf65f61a11 96 store_stack_complete
LancasterUniversity 14:6dcf65f61a11 97
LancasterUniversity 14:6dcf65f61a11 98 ;
LancasterUniversity 14:6dcf65f61a11 99 ; Now page in the new context.
LancasterUniversity 14:6dcf65f61a11 100 ; Update all registers except the PC. We can also safely ignore the STATUS register, as we're just a fiber scheduler.
LancasterUniversity 14:6dcf65f61a11 101 ;
LancasterUniversity 14:6dcf65f61a11 102 LDR R4, [R1, #56]
LancasterUniversity 14:6dcf65f61a11 103 MOV LR, R4
LancasterUniversity 14:6dcf65f61a11 104 LDR R6, [R1, #52]
LancasterUniversity 14:6dcf65f61a11 105 MOV SP, R6
LancasterUniversity 14:6dcf65f61a11 106
LancasterUniversity 14:6dcf65f61a11 107 ; Copy the stack in.
LancasterUniversity 14:6dcf65f61a11 108 ; n.b. we do this after setting the SP to make comparisons easier.
LancasterUniversity 14:6dcf65f61a11 109
LancasterUniversity 14:6dcf65f61a11 110 ; Skip this is we're given a NULL parameter for the stack.
LancasterUniversity 14:6dcf65f61a11 111 CMP R3, #0
LancasterUniversity 14:6dcf65f61a11 112 BEQ restore_stack_complete
LancasterUniversity 14:6dcf65f61a11 113
LancasterUniversity 14:6dcf65f61a11 114 LDR R4, [R1,#60] ; Load R4 with the fiber's defined stack_base.
LancasterUniversity 14:6dcf65f61a11 115
LancasterUniversity 14:6dcf65f61a11 116 restore_stack
LancasterUniversity 14:6dcf65f61a11 117 SUBS R4, #4
LancasterUniversity 14:6dcf65f61a11 118 SUBS R3, #4
LancasterUniversity 14:6dcf65f61a11 119
LancasterUniversity 14:6dcf65f61a11 120 LDR R5, [R3]
LancasterUniversity 14:6dcf65f61a11 121 STR R5, [R4]
LancasterUniversity 14:6dcf65f61a11 122
LancasterUniversity 14:6dcf65f61a11 123 CMP R4, R6
LancasterUniversity 14:6dcf65f61a11 124 BNE restore_stack
LancasterUniversity 14:6dcf65f61a11 125
LancasterUniversity 14:6dcf65f61a11 126 restore_stack_complete
LancasterUniversity 14:6dcf65f61a11 127 LDR R4, [R1, #48]
LancasterUniversity 14:6dcf65f61a11 128 MOV R12, R4
LancasterUniversity 14:6dcf65f61a11 129 LDR R4, [R1, #44]
LancasterUniversity 14:6dcf65f61a11 130 MOV R11, R4
LancasterUniversity 14:6dcf65f61a11 131 LDR R4, [R1, #40]
LancasterUniversity 14:6dcf65f61a11 132 MOV R10, R4
LancasterUniversity 14:6dcf65f61a11 133 LDR R4, [R1, #36]
LancasterUniversity 14:6dcf65f61a11 134 MOV R9, R4
LancasterUniversity 14:6dcf65f61a11 135 LDR R4, [R1, #32]
LancasterUniversity 14:6dcf65f61a11 136 MOV R8, R4
LancasterUniversity 14:6dcf65f61a11 137
LancasterUniversity 14:6dcf65f61a11 138 LDR R7, [R1, #28]
LancasterUniversity 14:6dcf65f61a11 139 LDR R6, [R1, #24]
LancasterUniversity 14:6dcf65f61a11 140 LDR R5, [R1, #20]
LancasterUniversity 14:6dcf65f61a11 141 LDR R4, [R1, #16]
LancasterUniversity 14:6dcf65f61a11 142 LDR R3, [R1, #12]
LancasterUniversity 14:6dcf65f61a11 143 LDR R2, [R1, #8]
LancasterUniversity 14:6dcf65f61a11 144 LDR R0, [R1, #0]
LancasterUniversity 14:6dcf65f61a11 145 LDR R1, [R1, #4]
LancasterUniversity 14:6dcf65f61a11 146
LancasterUniversity 14:6dcf65f61a11 147 ; Return to caller (scheduler).
LancasterUniversity 14:6dcf65f61a11 148 BX LR
LancasterUniversity 14:6dcf65f61a11 149
LancasterUniversity 14:6dcf65f61a11 150
LancasterUniversity 14:6dcf65f61a11 151 ; R0 Contains a pointer to the TCB of the fibre to snapshot
LancasterUniversity 14:6dcf65f61a11 152 ; R1 Contains a pointer to the base of the stack of the fibre being snapshotted
LancasterUniversity 14:6dcf65f61a11 153
LancasterUniversity 14:6dcf65f61a11 154 save_context
LancasterUniversity 14:6dcf65f61a11 155
LancasterUniversity 14:6dcf65f61a11 156 ; Write our core registers into the TCB
LancasterUniversity 14:6dcf65f61a11 157 ; First, store the general registers
LancasterUniversity 14:6dcf65f61a11 158
LancasterUniversity 14:6dcf65f61a11 159 STR R0, [R0,#0]
LancasterUniversity 14:6dcf65f61a11 160 STR R1, [R0,#4]
LancasterUniversity 14:6dcf65f61a11 161 STR R2, [R0,#8]
LancasterUniversity 14:6dcf65f61a11 162 STR R3, [R0,#12]
LancasterUniversity 14:6dcf65f61a11 163 STR R4, [R0,#16]
LancasterUniversity 14:6dcf65f61a11 164 STR R5, [R0,#20]
LancasterUniversity 14:6dcf65f61a11 165 STR R6, [R0,#24]
LancasterUniversity 14:6dcf65f61a11 166 STR R7, [R0,#28]
LancasterUniversity 14:6dcf65f61a11 167
LancasterUniversity 14:6dcf65f61a11 168 ; Now the high general purpose registers
LancasterUniversity 14:6dcf65f61a11 169 MOV R4, R8
LancasterUniversity 14:6dcf65f61a11 170 STR R4, [R0,#32]
LancasterUniversity 14:6dcf65f61a11 171 MOV R4, R9
LancasterUniversity 14:6dcf65f61a11 172 STR R4, [R0,#36]
LancasterUniversity 14:6dcf65f61a11 173 MOV R4, R10
LancasterUniversity 14:6dcf65f61a11 174 STR R4, [R0,#40]
LancasterUniversity 14:6dcf65f61a11 175 MOV R4, R11
LancasterUniversity 14:6dcf65f61a11 176 STR R4, [R0,#44]
LancasterUniversity 14:6dcf65f61a11 177 MOV R4, R12
LancasterUniversity 14:6dcf65f61a11 178 STR R4, [R0,#48]
LancasterUniversity 14:6dcf65f61a11 179
LancasterUniversity 14:6dcf65f61a11 180 ; Now the Stack and Link Register.
LancasterUniversity 14:6dcf65f61a11 181 ; As this context is only intended for use with a fiber scheduler,
LancasterUniversity 14:6dcf65f61a11 182 ; we don't need the PC.
LancasterUniversity 14:6dcf65f61a11 183 MOV R6, SP
LancasterUniversity 14:6dcf65f61a11 184 STR R6, [R0,#52]
LancasterUniversity 14:6dcf65f61a11 185 MOV R4, LR
LancasterUniversity 14:6dcf65f61a11 186 STR R4, [R0,#56]
LancasterUniversity 14:6dcf65f61a11 187
LancasterUniversity 14:6dcf65f61a11 188 ; Finally, Copy the stack. We do this to reduce RAM footprint, as stackis usually very small at the point
LancasterUniversity 14:6dcf65f61a11 189 ; of sceduling, but we need a lot of capacity for interrupt handling and other functions.
LancasterUniversity 14:6dcf65f61a11 190
LancasterUniversity 14:6dcf65f61a11 191 LDR R4, [R0,#60] ; Load R4 with the fiber's defined stack_base.
LancasterUniversity 14:6dcf65f61a11 192
LancasterUniversity 14:6dcf65f61a11 193 store_stack1
LancasterUniversity 14:6dcf65f61a11 194 SUBS R4, #4
LancasterUniversity 14:6dcf65f61a11 195 SUBS R1, #4
LancasterUniversity 14:6dcf65f61a11 196
LancasterUniversity 14:6dcf65f61a11 197 LDR R5, [R4]
LancasterUniversity 14:6dcf65f61a11 198 STR R5, [R1]
LancasterUniversity 14:6dcf65f61a11 199
LancasterUniversity 14:6dcf65f61a11 200 CMP R4, R6
LancasterUniversity 14:6dcf65f61a11 201 BNE store_stack1
LancasterUniversity 14:6dcf65f61a11 202
LancasterUniversity 14:6dcf65f61a11 203 ; Restore scratch registers.
LancasterUniversity 14:6dcf65f61a11 204
LancasterUniversity 14:6dcf65f61a11 205 LDR R7, [R0, #28]
LancasterUniversity 14:6dcf65f61a11 206 LDR R6, [R0, #24]
LancasterUniversity 14:6dcf65f61a11 207 LDR R5, [R0, #20]
LancasterUniversity 14:6dcf65f61a11 208 LDR R4, [R0, #16]
LancasterUniversity 14:6dcf65f61a11 209
LancasterUniversity 14:6dcf65f61a11 210 ; Return to caller (scheduler).
LancasterUniversity 14:6dcf65f61a11 211 BX LR
LancasterUniversity 14:6dcf65f61a11 212
LancasterUniversity 14:6dcf65f61a11 213
LancasterUniversity 14:6dcf65f61a11 214 ; R0 Contains a pointer to the TCB of the fiber to snapshot
LancasterUniversity 14:6dcf65f61a11 215 save_register_context
LancasterUniversity 14:6dcf65f61a11 216
LancasterUniversity 14:6dcf65f61a11 217 ; Write our core registers into the TCB
LancasterUniversity 14:6dcf65f61a11 218 ; First, store the general registers
LancasterUniversity 14:6dcf65f61a11 219
LancasterUniversity 14:6dcf65f61a11 220 STR R0, [R0,#0]
LancasterUniversity 14:6dcf65f61a11 221 STR R1, [R0,#4]
LancasterUniversity 14:6dcf65f61a11 222 STR R2, [R0,#8]
LancasterUniversity 14:6dcf65f61a11 223 STR R3, [R0,#12]
LancasterUniversity 14:6dcf65f61a11 224 STR R4, [R0,#16]
LancasterUniversity 14:6dcf65f61a11 225 STR R5, [R0,#20]
LancasterUniversity 14:6dcf65f61a11 226 STR R6, [R0,#24]
LancasterUniversity 14:6dcf65f61a11 227 STR R7, [R0,#28]
LancasterUniversity 14:6dcf65f61a11 228
LancasterUniversity 14:6dcf65f61a11 229 ; Now the high general purpose registers
LancasterUniversity 14:6dcf65f61a11 230 MOV R4, R8
LancasterUniversity 14:6dcf65f61a11 231 STR R4, [R0,#32]
LancasterUniversity 14:6dcf65f61a11 232 MOV R4, R9
LancasterUniversity 14:6dcf65f61a11 233 STR R4, [R0,#36]
LancasterUniversity 14:6dcf65f61a11 234 MOV R4, R10
LancasterUniversity 14:6dcf65f61a11 235 STR R4, [R0,#40]
LancasterUniversity 14:6dcf65f61a11 236 MOV R4, R11
LancasterUniversity 14:6dcf65f61a11 237 STR R4, [R0,#44]
LancasterUniversity 14:6dcf65f61a11 238 MOV R4, R12
LancasterUniversity 14:6dcf65f61a11 239 STR R4, [R0,#48]
LancasterUniversity 14:6dcf65f61a11 240
LancasterUniversity 14:6dcf65f61a11 241 ; Now the Stack Pointer and Link Register.
LancasterUniversity 14:6dcf65f61a11 242 ; As this context is only intended for use with a fiber scheduler,
LancasterUniversity 14:6dcf65f61a11 243 ; we don't need the PC.
LancasterUniversity 14:6dcf65f61a11 244 MOV R4, SP
LancasterUniversity 14:6dcf65f61a11 245 STR R4, [R0,#52]
LancasterUniversity 14:6dcf65f61a11 246 MOV R4, LR
LancasterUniversity 14:6dcf65f61a11 247 STR R4, [R0,#56]
LancasterUniversity 14:6dcf65f61a11 248
LancasterUniversity 14:6dcf65f61a11 249 ; Restore scratch registers.
LancasterUniversity 14:6dcf65f61a11 250 LDR R4, [R0, #16]
LancasterUniversity 14:6dcf65f61a11 251
LancasterUniversity 14:6dcf65f61a11 252 ; Return to caller (scheduler).
LancasterUniversity 14:6dcf65f61a11 253 BX LR
LancasterUniversity 14:6dcf65f61a11 254
LancasterUniversity 14:6dcf65f61a11 255
LancasterUniversity 14:6dcf65f61a11 256 restore_register_context
LancasterUniversity 14:6dcf65f61a11 257
LancasterUniversity 14:6dcf65f61a11 258 ;
LancasterUniversity 14:6dcf65f61a11 259 ; Now page in the new context.
LancasterUniversity 14:6dcf65f61a11 260 ; Update all registers except the PC. We can also safely ignore the STATUS register, as we're just a fiber scheduler.
LancasterUniversity 14:6dcf65f61a11 261 ;
LancasterUniversity 14:6dcf65f61a11 262 LDR R4, [R0, #56]
LancasterUniversity 14:6dcf65f61a11 263 MOV LR, R4
LancasterUniversity 14:6dcf65f61a11 264 LDR R4, [R0, #52]
LancasterUniversity 14:6dcf65f61a11 265 MOV SP, R4
LancasterUniversity 14:6dcf65f61a11 266
LancasterUniversity 14:6dcf65f61a11 267 ; High registers...
LancasterUniversity 14:6dcf65f61a11 268 LDR R4, [R0, #48]
LancasterUniversity 14:6dcf65f61a11 269 MOV R12, R4
LancasterUniversity 14:6dcf65f61a11 270 LDR R4, [R0, #44]
LancasterUniversity 14:6dcf65f61a11 271 MOV R11, R4
LancasterUniversity 14:6dcf65f61a11 272 LDR R4, [R0, #40]
LancasterUniversity 14:6dcf65f61a11 273 MOV R10, R4
LancasterUniversity 14:6dcf65f61a11 274 LDR R4, [R0, #36]
LancasterUniversity 14:6dcf65f61a11 275 MOV R9, R4
LancasterUniversity 14:6dcf65f61a11 276 LDR R4, [R0, #32]
LancasterUniversity 14:6dcf65f61a11 277 MOV R8, R4
LancasterUniversity 14:6dcf65f61a11 278
LancasterUniversity 14:6dcf65f61a11 279 ; Low registers...
LancasterUniversity 14:6dcf65f61a11 280 LDR R7, [R0, #28]
LancasterUniversity 14:6dcf65f61a11 281 LDR R6, [R0, #24]
LancasterUniversity 14:6dcf65f61a11 282 LDR R5, [R0, #20]
LancasterUniversity 14:6dcf65f61a11 283 LDR R4, [R0, #16]
LancasterUniversity 14:6dcf65f61a11 284 LDR R3, [R0, #12]
LancasterUniversity 14:6dcf65f61a11 285 LDR R2, [R0, #8]
LancasterUniversity 14:6dcf65f61a11 286 LDR R0, [R0, #0]
LancasterUniversity 14:6dcf65f61a11 287 LDR R1, [R0, #4]
LancasterUniversity 14:6dcf65f61a11 288
LancasterUniversity 14:6dcf65f61a11 289 ; Return to caller (normally the scheduler).
LancasterUniversity 14:6dcf65f61a11 290 BX LR
LancasterUniversity 14:6dcf65f61a11 291
LancasterUniversity 14:6dcf65f61a11 292 ALIGN
LancasterUniversity 14:6dcf65f61a11 293 END