Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

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.
  • Loading branch information...
commit 4b2a1d798b16cff17633e6aedfe99b9992fa30e4 1 parent 75b285a
@Ithamar Ithamar authored
View
110 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)
View
116 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;
-}*/
Please sign in to comment.
Something went wrong with that request. Please try again.