diff --git a/src/fiber/context/arm.cr b/src/fiber/context/arm.cr index 7f100262cb57..5bbb25f6522d 100644 --- a/src/fiber/context/arm.cr +++ b/src/fiber/context/arm.cr @@ -21,6 +21,8 @@ class Fiber @[NoInline] @[Naked] def self.swapcontext(current_context, new_context) : Nil + # r0 , r1 + # ARM assembly requires integer literals to be moved to a register before # being stored at an address; we use r4 as a scratch register that will be # overwritten by the new context. @@ -28,93 +30,64 @@ class Fiber # Eventually reset LR to zero to avoid the ARM unwinder to mistake the # context switch as a regular call. - {% if flag?(:armhf) %} - # r0 , r1 - {% if compare_versions(Crystal::LLVM_VERSION, "9.0.0") >= 0 %} - asm(" - // declare the presence of a conservative FPU to the ASM compiler - .fpu vfp - - stmdb sp!, {r0, r4-r11, lr} // push 1st argument + callee-saved registers - vstmdb sp!, {d8-d15} // push FPU registers - str sp, [r0, #0] // current_context.stack_top = sp - mov r4, #1 // current_context.resumable = 1 - str r4, [r0, #4] - - mov r4, #0 // new_context.resumable = 0 - str r4, [r1, #4] - ldr sp, [r1, #0] // sp = new_context.stack_top - vldmia sp!, {d8-d15} // pop FPU registers - ldmia sp!, {r0, r4-r11, lr} // pop 1st argument + callee-saved registers + {% if compare_versions(Crystal::LLVM_VERSION, "9.0.0") >= 0 %} + asm(" + {% if flag?(:armhf) %} + // declare the presence of a conservative FPU to the ASM compiler + .fpu vfp + {% end %} - // avoid a stack corruption that will confuse the unwinder - mov r1, lr - mov lr, #0 - mov pc, r1 - ") - {% else %} - # On LLVM < 9.0 using the previous code emits some additional - # instructions that breaks the context switching. - asm(" - // declare the presence of a conservative FPU to the ASM compiler - .fpu vfp + stmdb sp!, {r0, r4-r11, lr} // push 1st argument + callee-saved registers + {% if flag?(:armhf) %} + vstmdb sp!, {d8-d15} // push FPU registers + {% end %} + str sp, [r0, #0] // current_context.stack_top = sp + mov r4, #1 // current_context.resumable = 1 + str r4, [r0, #4] - stmdb sp!, {r0, r4-r11, lr} // push 1st argument + callee-saved registers - vstmdb sp!, {d8-d15} // push FPU registers - str sp, [$0, #0] // current_context.stack_top = sp - mov r4, #1 // current_context.resumable = 1 - str r4, [$0, #4] + mov r4, #0 // new_context.resumable = 0 + str r4, [r1, #4] + ldr sp, [r1, #0] // sp = new_context.stack_top + {% if flag?(:armhf) %} + vldmia sp!, {d8-d15} // pop FPU registers + {% end %} + ldmia sp!, {r0, r4-r11, lr} // pop 1st argument + callee-saved registers - mov r4, #0 // new_context.resumable = 0 - str r4, [$1, #4] - ldr sp, [$1, #0] // sp = new_context.stack_top - vldmia sp!, {d8-d15} // pop FPU registers - ldmia sp!, {r0, r4-r11, lr} // pop 1st argument + callee-saved registers - - // avoid a stack corruption that will confuse the unwinder - mov r1, lr - mov lr, #0 - mov pc, r1 - " :: "r"(current_context), "r"(new_context)) - {% end %} - {% elsif flag?(:arm) %} - {% if compare_versions(Crystal::LLVM_VERSION, "9.0.0") >= 0 %} - asm(" - stmdb sp!, {r0, r4-r11, lr} // push 1st argument + callee-saved registers - str sp, [r0, #0] // current_context.stack_top = sp - mov r4, #1 // current_context.resumable = 1 - str r4, [r0, #4] - - mov r4, #0 // new_context.resumable = 0 - str r4, [r1, #4] - ldr sp, [r1, #0] // sp = new_context.stack_top - ldmia sp!, {r0, r4-r11, lr} // pop 1st argument + callee-saved registers + // avoid a stack corruption that will confuse the unwinder + mov r1, lr + mov lr, #0 + mov pc, r1 + ") + {% else %} + # On LLVM < 9.0 using the previous code emits some additional + # instructions that breaks the context switching. + asm(" + {% if flag?(:armhf) %} + // declare the presence of a conservative FPU to the ASM compiler + .fpu vfp + {% end %} - // avoid a stack corruption that will confuse the unwinder - mov r1, lr - mov lr, #0 - mov pc, r1 - ") - {% else %} - # On LLVM < 9.0 using the previous code emits some additional - # instructions that breaks the context switching. - asm(" - stmdb sp!, {r0, r4-r11, lr} // push 1st argument + callee-saved registers - str sp, [$0, #0] // current_context.stack_top = sp - mov r4, #1 // current_context.resumable = 1 - str r4, [$0, #4] + stmdb sp!, {r0, r4-r11, lr} // push 1st argument + callee-saved registers + {% if flag?(:armhf) %} + vstmdb sp!, {d8-d15} // push FPU registers + {% end %} + str sp, [$0, #0] // current_context.stack_top = sp + mov r4, #1 // current_context.resumable = 1 + str r4, [$0, #4] - mov r4, #0 // new_context.resumable = 0 - str r4, [$1, #4] - ldr sp, [$1, #0] // sp = new_context.stack_top - ldmia sp!, {r0, r4-r11, lr} // pop 1st argument + callee-saved registers + mov r4, #0 // new_context.resumable = 0 + str r4, [$1, #4] + ldr sp, [$1, #0] // sp = new_context.stack_top + {% if flag?(:armhf) %} + vldmia sp!, {d8-d15} // pop FPU registers + {% end %} + ldmia sp!, {r0, r4-r11, lr} // pop 1st argument + callee-saved registers - // avoid a stack corruption that will confuse the unwinder - mov r1, lr - mov lr, #0 - mov pc, r1 - " :: "r"(current_context), "r"(new_context)) - {% end %} + // avoid a stack corruption that will confuse the unwinder + mov r1, lr + mov lr, #0 + mov pc, r1 + " :: "r"(current_context), "r"(new_context)) {% end %} end end