174 lines
4.2 KiB
ArmAsm
174 lines
4.2 KiB
ArmAsm
|
/*
|
||
|
* linux/arch/arm26/lib/uaccess-kernel.S
|
||
|
*
|
||
|
* Copyright (C) 1998 Russell King
|
||
|
*
|
||
|
* Note! Some code fragments found in here have a special calling
|
||
|
* convention - they are not APCS compliant!
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License version 2 as
|
||
|
* published by the Free Software Foundation.
|
||
|
*/
|
||
|
#include <linux/linkage.h>
|
||
|
#include <asm/assembler.h>
|
||
|
|
||
|
.text
|
||
|
|
||
|
//FIXME - surely this can be done in C not asm, removing the problem of keeping C and asm in sync? (this is a struct uaccess_t)
|
||
|
|
||
|
.globl uaccess_kernel
|
||
|
uaccess_kernel:
|
||
|
.word uaccess_kernel_put_byte
|
||
|
.word uaccess_kernel_get_byte
|
||
|
.word uaccess_kernel_put_half
|
||
|
.word uaccess_kernel_get_half
|
||
|
.word uaccess_kernel_put_word
|
||
|
.word uaccess_kernel_get_word
|
||
|
.word uaccess_kernel_put_dword
|
||
|
.word uaccess_kernel_copy
|
||
|
.word uaccess_kernel_copy
|
||
|
.word uaccess_kernel_clear
|
||
|
.word uaccess_kernel_strncpy
|
||
|
.word uaccess_kernel_strnlen
|
||
|
|
||
|
@ In : r0 = x, r1 = addr, r2 = error
|
||
|
@ Out: r2 = error
|
||
|
uaccess_kernel_put_byte:
|
||
|
stmfd sp!, {lr}
|
||
|
strb r0, [r1]
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
@ In : r0 = x, r1 = addr, r2 = error
|
||
|
@ Out: r2 = error
|
||
|
uaccess_kernel_put_half:
|
||
|
stmfd sp!, {lr}
|
||
|
strb r0, [r1]
|
||
|
mov r0, r0, lsr #8
|
||
|
strb r0, [r1, #1]
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
@ In : r0 = x, r1 = addr, r2 = error
|
||
|
@ Out: r2 = error
|
||
|
uaccess_kernel_put_word:
|
||
|
stmfd sp!, {lr}
|
||
|
str r0, [r1]
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
@ In : r0 = x, r1 = addr, r2 = error
|
||
|
@ Out: r2 = error
|
||
|
uaccess_kernel_put_dword:
|
||
|
stmfd sp!, {lr}
|
||
|
str r0, [r1], #4
|
||
|
str r0, [r1], #0
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
@ In : r0 = addr, r1 = error
|
||
|
@ Out: r0 = x, r1 = error
|
||
|
uaccess_kernel_get_byte:
|
||
|
stmfd sp!, {lr}
|
||
|
ldrb r0, [r0]
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
@ In : r0 = addr, r1 = error
|
||
|
@ Out: r0 = x, r1 = error
|
||
|
uaccess_kernel_get_half:
|
||
|
stmfd sp!, {lr}
|
||
|
ldr r0, [r0]
|
||
|
mov r0, r0, lsl #16
|
||
|
mov r0, r0, lsr #16
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
@ In : r0 = addr, r1 = error
|
||
|
@ Out: r0 = x, r1 = error
|
||
|
uaccess_kernel_get_word:
|
||
|
stmfd sp!, {lr}
|
||
|
ldr r0, [r0]
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
|
||
|
/* Prototype: int uaccess_kernel_copy(void *to, const char *from, size_t n)
|
||
|
* Purpose : copy a block to kernel memory from kernel memory
|
||
|
* Params : to - kernel memory
|
||
|
* : from - kernel memory
|
||
|
* : n - number of bytes to copy
|
||
|
* Returns : Number of bytes NOT copied.
|
||
|
*/
|
||
|
uaccess_kernel_copy:
|
||
|
stmfd sp!, {lr}
|
||
|
bl memcpy
|
||
|
mov r0, #0
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
/* Prototype: int uaccess_kernel_clear(void *addr, size_t sz)
|
||
|
* Purpose : clear some kernel memory
|
||
|
* Params : addr - kernel memory address to clear
|
||
|
* : sz - number of bytes to clear
|
||
|
* Returns : number of bytes NOT cleared
|
||
|
*/
|
||
|
uaccess_kernel_clear:
|
||
|
stmfd sp!, {lr}
|
||
|
mov r2, #0
|
||
|
cmp r1, #4
|
||
|
blt 2f
|
||
|
ands ip, r0, #3
|
||
|
beq 1f
|
||
|
cmp ip, #1
|
||
|
strb r2, [r0], #1
|
||
|
strleb r2, [r0], #1
|
||
|
strltb r2, [r0], #1
|
||
|
rsb ip, ip, #4
|
||
|
sub r1, r1, ip @ 7 6 5 4 3 2 1
|
||
|
1: subs r1, r1, #8 @ -1 -2 -3 -4 -5 -6 -7
|
||
|
bmi 2f
|
||
|
str r2, [r0], #4
|
||
|
str r2, [r0], #4
|
||
|
b 1b
|
||
|
2: adds r1, r1, #4 @ 3 2 1 0 -1 -2 -3
|
||
|
strpl r2, [r0], #4
|
||
|
tst r1, #2 @ 1x 1x 0x 0x 1x 1x 0x
|
||
|
strneb r2, [r0], #1
|
||
|
strneb r2, [r0], #1
|
||
|
tst r1, #1 @ x1 x0 x1 x0 x1 x0 x1
|
||
|
strneb r2, [r0], #1
|
||
|
mov r0, #0
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
/* Prototype: size_t uaccess_kernel_strncpy(char *dst, char *src, size_t len)
|
||
|
* Purpose : copy a string from kernel memory to kernel memory
|
||
|
* Params : dst - kernel memory destination
|
||
|
* : src - kernel memory source
|
||
|
* : len - maximum length of string
|
||
|
* Returns : number of characters copied
|
||
|
*/
|
||
|
uaccess_kernel_strncpy:
|
||
|
stmfd sp!, {lr}
|
||
|
mov ip, r2
|
||
|
1: subs r2, r2, #1
|
||
|
bmi 2f
|
||
|
ldrb r3, [r1], #1
|
||
|
strb r3, [r0], #1
|
||
|
teq r3, #0
|
||
|
bne 1b
|
||
|
2: subs r0, ip, r2
|
||
|
ldmfd sp!, {pc}^
|
||
|
|
||
|
/* Prototype: int uaccess_kernel_strlen(char *str, long n)
|
||
|
* Purpose : get length of a string in kernel memory
|
||
|
* Params : str - address of string in kernel memory
|
||
|
* Returns : length of string *including terminator*,
|
||
|
* or zero on exception, or n + 1 if too long
|
||
|
*/
|
||
|
uaccess_kernel_strnlen:
|
||
|
stmfd sp!, {lr}
|
||
|
mov r2, r0
|
||
|
1: ldrb r1, [r0], #1
|
||
|
teq r1, #0
|
||
|
beq 2f
|
||
|
subs r1, r1, #1
|
||
|
bne 1b
|
||
|
add r0, r0, #1
|
||
|
2: sub r0, r0, r2
|
||
|
ldmfd sp!, {pc}^
|
||
|
|