From 5db29719033eed38909c6ebdf335f312f08a57c4 Mon Sep 17 00:00:00 2001 From: Piotr Tworek Date: Fri, 13 Nov 2020 01:16:19 +0100 Subject: [PATCH] base-hw/arm_v7a: Mark r1 as out in Kernel::call64 In case of arm_v7a Kernel::call64 the syscall will use both r0 and r1 as output registers. Unfortunately the inline asm does not reflect this and only r0 is explicitly specified as output. GCC manages to produce output which we'd like to see. Clang on the other hand takes adventage of the fact r1 should not be touched by swi and produces fewer instructions which do what the code describes, but not what we actually want. Basically the code which we want and is generated by GCC is: svc 0 mov r2, r0 mov r0, r1 mov r1, r2 bx lr Clang on the other hand generates correct assembly given the code, but incorrect given what the function is supposed to do: svc 0 mov r1, r0 mov r0, #0 bx lr Both GCC and clang generate the same, expected assembly output when r1 is marked as output register from the inline asm swi call. Fixes #3951 --- repos/base-hw/src/lib/base/arm/kernel/interface.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/repos/base-hw/src/lib/base/arm/kernel/interface.cc b/repos/base-hw/src/lib/base/arm/kernel/interface.cc index ecd90f3f85..442f21c7d8 100644 --- a/repos/base-hw/src/lib/base/arm/kernel/interface.cc +++ b/repos/base-hw/src/lib/base/arm/kernel/interface.cc @@ -60,7 +60,10 @@ Call_ret_64 Kernel::call64(Call_arg arg_0) { register Call_arg arg_0_reg asm("r0") = arg_0; register Call_arg arg_1_reg asm("r1"); - asm volatile(CALL_1_SWI); + + /* in this particular case, both r0 and r1 are used as output */ + asm volatile(CALL_1_SWI, "+r"(arg_1_reg)); + return ((Call_ret_64)arg_0_reg) << 32 | (Call_ret_64)arg_1_reg; }