hrev44819 adds 1 changeset to branch 'master' old head: 75b285a9699908edbcab1c081a7c53b7d3b3ca76 new head: 4b2a1d798b16cff17633e6aedfe99b9992fa30e4 ---------------------------------------------------------------------------- 4b2a1d7: ARM: implement arch_cpu_user_memcpy/memset/strlcpy functions Remove the dummies from the C code and implement them in assembly, due to the label referencing issues with the fault handler. This code is ripe for optimisation, my ARM assembly is pretty basic ;) Does work though, and gets us one step closer to a full arch. [ Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev44819 Commit: 4b2a1d798b16cff17633e6aedfe99b9992fa30e4 URL: http://cgit.haiku-os.org/haiku/commit/?id=4b2a1d7 Author: Ithamar R. Adema <ithamar@xxxxxxxxxxxxxxxxxxx> Date: Mon Nov 12 19:03:48 2012 UTC ---------------------------------------------------------------------------- 2 files changed, 110 insertions(+), 116 deletions(-) src/system/kernel/arch/arm/arch_asm.S | 110 ++++++++++++++++++++++++++ src/system/kernel/arch/arm/arch_cpu.cpp | 116 ---------------------------- ---------------------------------------------------------------------------- diff --git a/src/system/kernel/arch/arm/arch_asm.S b/src/system/kernel/arch/arm/arch_asm.S index c51089c..eb570a5 100644 --- a/src/system/kernel/arch/arm/arch_asm.S +++ b/src/system/kernel/arch/arm/arch_asm.S @@ -94,6 +94,116 @@ FUNCTION(arm_get_far): bx lr FUNCTION_END(arm_get_far) +/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */ +FUNCTION(arch_cpu_user_memcpy): + stmfd sp!, { r4-r6 } + ldr r6, [r3] + ldr r4, =.L_user_memcpy_error + str r4, [r3] /* set fault handler */ + mov r4, r2, lsr #2 /* size / 4 */ +1: + ldr r5, [r1] + str r5, [r0] + add r1, #4 + add r0, #4 + sub r4, #1 + bne 1b +2: + and r4, r2, #3 /* size % 4 */ + ldrb r5, [r1] + strb r5, [r0] + add r1, #1 + add r0, #1 + sub r4, #1 + bne 2b + + str r6, [r3] /* restore fault handler */ + mov r0, #0 + ldmfd sp!, { r4-r6 } + bx lr + +.L_user_memcpy_error: + str r6, [r3] /* restore fault handler */ + mov r0, #-1 + + ldmfd sp!, { r4-r6 } + bx lr +FUNCTION_END(arch_cpu_user_memcpy) + +/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */ +FUNCTION(arch_cpu_user_memset): + stmfd sp!, { r4-r5 } + ldr r5, [r3] + ldr r4, =.L_user_memset_error + str r4, [r3] + + and r1, r1, #0xff + add r1, r1, lsl #8 + add r1, r1, lsl #16 + add r1, r1, lsl #24 + + mov r4, r2, lsr #2 /* count / 4 */ +1: + str r1, [r0] + add r0, r0, #4 + sub r4, r4, #1 + bne 1b + + and r4, r2, #3 /* count % 4 */ +2: + strb r1, [r0] + add r0, r0, #1 + sub r4, r4, #1 + bne 2b + + mov r0, #0 + str r5, [r3] + + ldmfd sp!, { r4-r5 } + bx lr + +.L_user_memset_error: + mov r0, #-1 + str r5, [r3] + + ldmfd sp!, { r4-r5 } + bx lr +FUNCTION_END(arch_cpu_user_memset) + +/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */ +FUNCTION(arch_cpu_user_strlcpy): + stmfd sp!, { r4-r6 } + ldr r5, [r3] + ldr r4, =.L_user_strlcpy_error + str r4, [r3] + mov r6, #0 +1: + ldrb r4, [r1, r6] + strb r4, [r0, r6] + add r6, r6, #1 + and r4, #0xff /* done yet? */ + beq 2f + cmp r6, r2 /* reached max length? */ + blt 1b +2: + mov r4, #0 + strb r4, [r0, r6] + + mov r0, r4 /* return B_OK */ + str r5, [r3] /* restore fault handler */ + + ldmfd sp!, { r4-r6 } + bx lr + +.L_user_strlcpy_error: + mov r0, #-1 + str r5, [r3] + + ldmfd sp!, { r4-r6 } + bx lr +FUNCTION_END(arch_cpu_user_strlcpy) + + /*! \fn void arch_debug_call_with_fault_handler(cpu_ent* cpu, jmp_buf jumpBuffer, void (*function)(void*), void* parameter) diff --git a/src/system/kernel/arch/arm/arch_cpu.cpp b/src/system/kernel/arch/arm/arch_cpu.cpp index 65d4795..7021427 100644 --- a/src/system/kernel/arch/arm/arch_cpu.cpp +++ b/src/system/kernel/arch/arm/arch_cpu.cpp @@ -159,119 +159,3 @@ arch_cpu_user_TLB_invalidate(void) */ #warning WRITEME } - - -// TODO: all functions that use fault handlers need to be implemented -// in assembly due to problems passing in label addresses in gcc4. -status_t -arch_cpu_user_memcpy(void *to, const void *from, size_t size, - addr_t *faultHandler) -{ -#warning WRITEME -/* - char *tmp = (char *)to; - char *s = (char *)from; - addr_t oldFaultHandler = *faultHandler; - - if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) - goto error; - - while (size--) - *tmp++ = *s++; - - *faultHandler = oldFaultHandler; - return 0; - -error: - *faultHandler = oldFaultHandler;*/ - return B_BAD_ADDRESS; -} - - -/** \brief Copies at most (\a size - 1) characters from the string in \a from to - * the string in \a to, NULL-terminating the result. - * - * \param to Pointer to the destination C-string. - * \param from Pointer to the source C-string. - * \param size Size in bytes of the string buffer pointed to by \a to. - * - * \return strlen(\a from). - */ - -ssize_t -arch_cpu_user_strlcpy(char *to, const char *from, - size_t size, addr_t *faultHandler) -{ -#warning WRITEME -/* - int from_length = 0; - addr_t oldFaultHandler = *faultHandler; - - if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) - goto error; - - if (size > 0) { - to[--size] = '\0'; - // copy - for ( ; size; size--, from_length++, to++, from++) { - if ((*to = *from) == '\0') - break; - } - } - // count any leftover from chars - while (*from++ != '\0') - from_length++; - - *faultHandler = oldFaultHandler; - return from_length; - -error: - *faultHandler = oldFaultHandler;*/ - return B_BAD_ADDRESS; -} - - -status_t -arch_cpu_user_memset(void *s, char c, size_t count, addr_t *faultHandler) -{ -#warning WRITEME - -/* - char *xs = (char *)s; - addr_t oldFaultHandler = *faultHandler; - - if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) - goto error; - - while (count--) - *xs++ = c; - - *faultHandler = oldFaultHandler; - return 0; - -error: - *faultHandler = oldFaultHandler;*/ - - return B_BAD_ADDRESS; -} - - -// The purpose of this function is to trick the compiler. When setting the -// page_handler to a label that is obviously (to the compiler) never used, -// it may reorganize the control flow, so that the labeled part is optimized -// away. -// By invoking the function like this -// -// if (m68k_set_fault_handler(faultHandler, (addr_t)&&error)) -// goto error; -// -// the compiler has to keep the labeled code, since it can't guess the return -// value of this (non-inlinable) function. At least in my tests it worked that -// way, and I hope it will continue to work like this in the future. -// -/*bool -m68k_set_fault_handler(addr_t *handlerLocation, addr_t handler) -{ - *handlerLocation = handler; - return false; -}*/