split kernel lib sources into their own directory and handled the section
differences with a partial link and a special link script
This commit is contained in:
43
kernel/lib/Makefile
Normal file
43
kernel/lib/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
#
|
||||
# Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
# All rights reserved.
|
||||
#
|
||||
# This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
# adhered to.
|
||||
#
|
||||
# Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
# in the code are not to be removed.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
# provided that the following conditions are met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
# the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
# the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
MAKEFLAGS += -rR
|
||||
CRBASEDIR := $(abspath ../..)
|
||||
include $(CRBASEDIR)/armcompile.mk
|
||||
|
||||
LIB_OBJS = divide.o qdivrem.o intlib.o objhelp.o rbtree.o str.o strcopymem.o strcomparemem.o strsetmem.o lib_guids.o
|
||||
|
||||
all: kernel-lib.o
|
||||
|
||||
kernel-lib.o: $(LIB_OBJS) kernel-lib.lds
|
||||
$(LD) -r -T kernel-lib.lds $(LIB_OBJS) -o kernel-lib.o
|
||||
|
||||
clean:
|
||||
-rm *.o *.s *.lds
|
||||
477
kernel/lib/divide.S
Normal file
477
kernel/lib/divide.S
Normal file
@@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Portions of this file are subject to the following notices:
|
||||
*
|
||||
* Copyright (C) 2012 Andrew Turner
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Matt Thomas of 3am Software Foundry.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/* Derived from FreeBSD libkern divsi3.S, uldivmod.S, and ldivmod.S, munged by Erbo to COMROGUE standards */
|
||||
.globl __aeabi_uidiv
|
||||
.globl __aeabi_uidivmod
|
||||
__aeabi_uidiv:
|
||||
__aeabi_uidivmod:
|
||||
eor r0, r1, r0 /* r0 = r0 / r1; r1 = r0 % r1 */
|
||||
eor r1, r0, r1
|
||||
eor r0, r1, r0 /* r0 = r1 / r0; r1 = r1 % r0 */
|
||||
|
||||
cmp r0, #1
|
||||
bcc .L_overflow
|
||||
beq .L_divide_l0
|
||||
mov ip, #0
|
||||
movs r1, r1
|
||||
bpl .L_divide_l1
|
||||
orr ip, ip, #0x20000000 /* indicates r1 is negative */
|
||||
movs r1, r1, lsr #1
|
||||
orrcs ip, ip, #0x10000000 /* indicates bit 0 of r1 */
|
||||
b .L_divide_l1
|
||||
|
||||
.L_divide_l0:
|
||||
mov r0, r1 /* r0 == 1 */
|
||||
mov r1, #0
|
||||
bx lr
|
||||
|
||||
.globl __aeabi_idiv
|
||||
.globl __aeabi_idivmod
|
||||
__aeabi_idiv:
|
||||
__aeabi_idivmod:
|
||||
eor r0, r1, r0 /* r0 = r0 / r1; r1 = r0 % r1 */
|
||||
eor r1, r0, r1
|
||||
eor r0, r1, r0 /* r0 = r1 / r0; r1 = r1 % r0 */
|
||||
|
||||
cmp r0, #1
|
||||
bcc .L_overflow
|
||||
beq .L_divide_l0
|
||||
ands ip, r0, #0x80000000
|
||||
rsbmi r0, r0, #0
|
||||
ands r2, r1, #0x80000000
|
||||
eor ip, ip, r2
|
||||
rsbmi r1, r1, #0
|
||||
orr ip, r2, ip, lsr #1 /* bit 0x40000000 = negative division, bit 0x80000000 = negative remainder */
|
||||
|
||||
.L_divide_l1:
|
||||
mov r2, #1
|
||||
mov r3, #0
|
||||
|
||||
/*
|
||||
* If the highest bit of the dividend is set, we have to be
|
||||
* careful when shifting the divisor. Test this.
|
||||
*/
|
||||
movs r1, r1
|
||||
bpl .L_old_code
|
||||
|
||||
/*
|
||||
* At this point, the highest bit of r1 is known to be set.
|
||||
* We abuse this below in the tst instructions.
|
||||
*/
|
||||
tst r1, r0 /*, lsl #0 */
|
||||
bmi .L_divide_b1
|
||||
tst r1, r0, lsl #1
|
||||
bmi .L_divide_b2
|
||||
tst r1, r0, lsl #2
|
||||
bmi .L_divide_b3
|
||||
tst r1, r0, lsl #3
|
||||
bmi .L_divide_b4
|
||||
tst r1, r0, lsl #4
|
||||
bmi .L_divide_b5
|
||||
tst r1, r0, lsl #5
|
||||
bmi .L_divide_b6
|
||||
tst r1, r0, lsl #6
|
||||
bmi .L_divide_b7
|
||||
tst r1, r0, lsl #7
|
||||
bmi .L_divide_b8
|
||||
tst r1, r0, lsl #8
|
||||
bmi .L_divide_b9
|
||||
tst r1, r0, lsl #9
|
||||
bmi .L_divide_b10
|
||||
tst r1, r0, lsl #10
|
||||
bmi .L_divide_b11
|
||||
tst r1, r0, lsl #11
|
||||
bmi .L_divide_b12
|
||||
tst r1, r0, lsl #12
|
||||
bmi .L_divide_b13
|
||||
tst r1, r0, lsl #13
|
||||
bmi .L_divide_b14
|
||||
tst r1, r0, lsl #14
|
||||
bmi .L_divide_b15
|
||||
tst r1, r0, lsl #15
|
||||
bmi .L_divide_b16
|
||||
tst r1, r0, lsl #16
|
||||
bmi .L_divide_b17
|
||||
tst r1, r0, lsl #17
|
||||
bmi .L_divide_b18
|
||||
tst r1, r0, lsl #18
|
||||
bmi .L_divide_b19
|
||||
tst r1, r0, lsl #19
|
||||
bmi .L_divide_b20
|
||||
tst r1, r0, lsl #20
|
||||
bmi .L_divide_b21
|
||||
tst r1, r0, lsl #21
|
||||
bmi .L_divide_b22
|
||||
tst r1, r0, lsl #22
|
||||
bmi .L_divide_b23
|
||||
tst r1, r0, lsl #23
|
||||
bmi .L_divide_b24
|
||||
tst r1, r0, lsl #24
|
||||
bmi .L_divide_b25
|
||||
tst r1, r0, lsl #25
|
||||
bmi .L_divide_b26
|
||||
tst r1, r0, lsl #26
|
||||
bmi .L_divide_b27
|
||||
tst r1, r0, lsl #27
|
||||
bmi .L_divide_b28
|
||||
tst r1, r0, lsl #28
|
||||
bmi .L_divide_b29
|
||||
tst r1, r0, lsl #29
|
||||
bmi .L_divide_b30
|
||||
tst r1, r0, lsl #30
|
||||
bmi .L_divide_b31
|
||||
/*
|
||||
* instead of:
|
||||
* tst r1, r0, lsl #31
|
||||
* bmi .L_divide_b32
|
||||
*/
|
||||
b .L_divide_b32
|
||||
|
||||
.L_old_code:
|
||||
cmp r1, r0
|
||||
bcc .L_divide_b0
|
||||
cmp r1, r0, lsl #1
|
||||
bcc .L_divide_b1
|
||||
cmp r1, r0, lsl #2
|
||||
bcc .L_divide_b2
|
||||
cmp r1, r0, lsl #3
|
||||
bcc .L_divide_b3
|
||||
cmp r1, r0, lsl #4
|
||||
bcc .L_divide_b4
|
||||
cmp r1, r0, lsl #5
|
||||
bcc .L_divide_b5
|
||||
cmp r1, r0, lsl #6
|
||||
bcc .L_divide_b6
|
||||
cmp r1, r0, lsl #7
|
||||
bcc .L_divide_b7
|
||||
cmp r1, r0, lsl #8
|
||||
bcc .L_divide_b8
|
||||
cmp r1, r0, lsl #9
|
||||
bcc .L_divide_b9
|
||||
cmp r1, r0, lsl #10
|
||||
bcc .L_divide_b10
|
||||
cmp r1, r0, lsl #11
|
||||
bcc .L_divide_b11
|
||||
cmp r1, r0, lsl #12
|
||||
bcc .L_divide_b12
|
||||
cmp r1, r0, lsl #13
|
||||
bcc .L_divide_b13
|
||||
cmp r1, r0, lsl #14
|
||||
bcc .L_divide_b14
|
||||
cmp r1, r0, lsl #15
|
||||
bcc .L_divide_b15
|
||||
cmp r1, r0, lsl #16
|
||||
bcc .L_divide_b16
|
||||
cmp r1, r0, lsl #17
|
||||
bcc .L_divide_b17
|
||||
cmp r1, r0, lsl #18
|
||||
bcc .L_divide_b18
|
||||
cmp r1, r0, lsl #19
|
||||
bcc .L_divide_b19
|
||||
cmp r1, r0, lsl #20
|
||||
bcc .L_divide_b20
|
||||
cmp r1, r0, lsl #21
|
||||
bcc .L_divide_b21
|
||||
cmp r1, r0, lsl #22
|
||||
bcc .L_divide_b22
|
||||
cmp r1, r0, lsl #23
|
||||
bcc .L_divide_b23
|
||||
cmp r1, r0, lsl #24
|
||||
bcc .L_divide_b24
|
||||
cmp r1, r0, lsl #25
|
||||
bcc .L_divide_b25
|
||||
cmp r1, r0, lsl #26
|
||||
bcc .L_divide_b26
|
||||
cmp r1, r0, lsl #27
|
||||
bcc .L_divide_b27
|
||||
cmp r1, r0, lsl #28
|
||||
bcc .L_divide_b28
|
||||
cmp r1, r0, lsl #29
|
||||
bcc .L_divide_b29
|
||||
cmp r1, r0, lsl #30
|
||||
bcc .L_divide_b30
|
||||
.L_divide_b32:
|
||||
cmp r1, r0, lsl #31
|
||||
subhs r1, r1,r0, lsl #31
|
||||
addhs r3, r3,r2, lsl #31
|
||||
.L_divide_b31:
|
||||
cmp r1, r0, lsl #30
|
||||
subhs r1, r1,r0, lsl #30
|
||||
addhs r3, r3,r2, lsl #30
|
||||
.L_divide_b30:
|
||||
cmp r1, r0, lsl #29
|
||||
subhs r1, r1,r0, lsl #29
|
||||
addhs r3, r3,r2, lsl #29
|
||||
.L_divide_b29:
|
||||
cmp r1, r0, lsl #28
|
||||
subhs r1, r1,r0, lsl #28
|
||||
addhs r3, r3,r2, lsl #28
|
||||
.L_divide_b28:
|
||||
cmp r1, r0, lsl #27
|
||||
subhs r1, r1,r0, lsl #27
|
||||
addhs r3, r3,r2, lsl #27
|
||||
.L_divide_b27:
|
||||
cmp r1, r0, lsl #26
|
||||
subhs r1, r1,r0, lsl #26
|
||||
addhs r3, r3,r2, lsl #26
|
||||
.L_divide_b26:
|
||||
cmp r1, r0, lsl #25
|
||||
subhs r1, r1,r0, lsl #25
|
||||
addhs r3, r3,r2, lsl #25
|
||||
.L_divide_b25:
|
||||
cmp r1, r0, lsl #24
|
||||
subhs r1, r1,r0, lsl #24
|
||||
addhs r3, r3,r2, lsl #24
|
||||
.L_divide_b24:
|
||||
cmp r1, r0, lsl #23
|
||||
subhs r1, r1,r0, lsl #23
|
||||
addhs r3, r3,r2, lsl #23
|
||||
.L_divide_b23:
|
||||
cmp r1, r0, lsl #22
|
||||
subhs r1, r1,r0, lsl #22
|
||||
addhs r3, r3,r2, lsl #22
|
||||
.L_divide_b22:
|
||||
cmp r1, r0, lsl #21
|
||||
subhs r1, r1,r0, lsl #21
|
||||
addhs r3, r3,r2, lsl #21
|
||||
.L_divide_b21:
|
||||
cmp r1, r0, lsl #20
|
||||
subhs r1, r1,r0, lsl #20
|
||||
addhs r3, r3,r2, lsl #20
|
||||
.L_divide_b20:
|
||||
cmp r1, r0, lsl #19
|
||||
subhs r1, r1,r0, lsl #19
|
||||
addhs r3, r3,r2, lsl #19
|
||||
.L_divide_b19:
|
||||
cmp r1, r0, lsl #18
|
||||
subhs r1, r1,r0, lsl #18
|
||||
addhs r3, r3,r2, lsl #18
|
||||
.L_divide_b18:
|
||||
cmp r1, r0, lsl #17
|
||||
subhs r1, r1,r0, lsl #17
|
||||
addhs r3, r3,r2, lsl #17
|
||||
.L_divide_b17:
|
||||
cmp r1, r0, lsl #16
|
||||
subhs r1, r1,r0, lsl #16
|
||||
addhs r3, r3,r2, lsl #16
|
||||
.L_divide_b16:
|
||||
cmp r1, r0, lsl #15
|
||||
subhs r1, r1,r0, lsl #15
|
||||
addhs r3, r3,r2, lsl #15
|
||||
.L_divide_b15:
|
||||
cmp r1, r0, lsl #14
|
||||
subhs r1, r1,r0, lsl #14
|
||||
addhs r3, r3,r2, lsl #14
|
||||
.L_divide_b14:
|
||||
cmp r1, r0, lsl #13
|
||||
subhs r1, r1,r0, lsl #13
|
||||
addhs r3, r3,r2, lsl #13
|
||||
.L_divide_b13:
|
||||
cmp r1, r0, lsl #12
|
||||
subhs r1, r1,r0, lsl #12
|
||||
addhs r3, r3,r2, lsl #12
|
||||
.L_divide_b12:
|
||||
cmp r1, r0, lsl #11
|
||||
subhs r1, r1,r0, lsl #11
|
||||
addhs r3, r3,r2, lsl #11
|
||||
.L_divide_b11:
|
||||
cmp r1, r0, lsl #10
|
||||
subhs r1, r1,r0, lsl #10
|
||||
addhs r3, r3,r2, lsl #10
|
||||
.L_divide_b10:
|
||||
cmp r1, r0, lsl #9
|
||||
subhs r1, r1,r0, lsl #9
|
||||
addhs r3, r3,r2, lsl #9
|
||||
.L_divide_b9:
|
||||
cmp r1, r0, lsl #8
|
||||
subhs r1, r1,r0, lsl #8
|
||||
addhs r3, r3,r2, lsl #8
|
||||
.L_divide_b8:
|
||||
cmp r1, r0, lsl #7
|
||||
subhs r1, r1,r0, lsl #7
|
||||
addhs r3, r3,r2, lsl #7
|
||||
.L_divide_b7:
|
||||
cmp r1, r0, lsl #6
|
||||
subhs r1, r1,r0, lsl #6
|
||||
addhs r3, r3,r2, lsl #6
|
||||
.L_divide_b6:
|
||||
cmp r1, r0, lsl #5
|
||||
subhs r1, r1,r0, lsl #5
|
||||
addhs r3, r3,r2, lsl #5
|
||||
.L_divide_b5:
|
||||
cmp r1, r0, lsl #4
|
||||
subhs r1, r1,r0, lsl #4
|
||||
addhs r3, r3,r2, lsl #4
|
||||
.L_divide_b4:
|
||||
cmp r1, r0, lsl #3
|
||||
subhs r1, r1,r0, lsl #3
|
||||
addhs r3, r3,r2, lsl #3
|
||||
.L_divide_b3:
|
||||
cmp r1, r0, lsl #2
|
||||
subhs r1, r1,r0, lsl #2
|
||||
addhs r3, r3,r2, lsl #2
|
||||
.L_divide_b2:
|
||||
cmp r1, r0, lsl #1
|
||||
subhs r1, r1,r0, lsl #1
|
||||
addhs r3, r3,r2, lsl #1
|
||||
.L_divide_b1:
|
||||
cmp r1, r0
|
||||
subhs r1, r1, r0
|
||||
addhs r3, r3, r2
|
||||
.L_divide_b0:
|
||||
|
||||
tst ip, #0x20000000
|
||||
bne .L_udivide_l1
|
||||
mov r0, r3
|
||||
cmp ip, #0
|
||||
rsbmi r1, r1, #0
|
||||
movs ip, ip, lsl #1
|
||||
bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */
|
||||
rsbmi r0, r0, #0
|
||||
bx lr
|
||||
|
||||
.L_udivide_l1:
|
||||
tst ip, #0x10000000
|
||||
mov r1, r1, lsl #1
|
||||
orrne r1, r1, #1
|
||||
mov r3, r3, lsl #1
|
||||
cmp r1, r0
|
||||
subhs r1, r1, r0
|
||||
addhs r3, r3, r2
|
||||
mov r0, r3
|
||||
bx lr
|
||||
|
||||
.L_overflow:
|
||||
/* TODO: cause an exception or something? */
|
||||
mvn r0, #0
|
||||
bx lr
|
||||
|
||||
.globl __aeabi_uldivmod
|
||||
__aeabi_uldivmod:
|
||||
push {r4,lr}
|
||||
sub sp, sp, #8
|
||||
mov r4, sp
|
||||
push {r4}
|
||||
bl __qdivrem
|
||||
pop {r4}
|
||||
/*
|
||||
* The remainder is already on the stack just waiting to be popped
|
||||
* into r2/r3.
|
||||
*/
|
||||
pop {r2-r4,lr}
|
||||
bx lr
|
||||
|
||||
.globl __aeabi_ldivmod
|
||||
__aeabi_ldivmod:
|
||||
push {r4-r5, sl, lr}
|
||||
mov r5, #0 /* r5 = negative indicator */
|
||||
|
||||
cmp r3, #0
|
||||
bge 2f
|
||||
eor r5, r5, #1 /* flip quotient sign */
|
||||
bl .Lnegate_b
|
||||
bcs .Lmaxdenom
|
||||
|
||||
2:
|
||||
cmp r1, #0
|
||||
/* bge 3f */
|
||||
eorlt r5, r5, #3 /* flip quotient sign, flip remainder sign */
|
||||
bllt .Lnegate_a
|
||||
3:
|
||||
/*
|
||||
* Arguments are setup, allocate some stack for the remainder
|
||||
* and call __qdivrem for the heavy lifting.
|
||||
*/
|
||||
sub sp, sp, #8
|
||||
mov r4, sp /* pointer to remainder */
|
||||
push {r4}
|
||||
bl __qdivrem
|
||||
pop {r4}
|
||||
|
||||
teq r5, #0 /* any signs to flip? */
|
||||
/*
|
||||
* The quotient is already in the right place and neither value
|
||||
* needs its sign flipped.
|
||||
*/
|
||||
popeq {r2-r5, sl, lr}
|
||||
bxeq lr
|
||||
|
||||
pop {r2, r3}
|
||||
tst r5, #2 /* does remainder need to be negative? */
|
||||
bleq .Lnegate_b
|
||||
tst r5, #1 /* does quotient need to be negative? */
|
||||
bleq .Lnegate_a
|
||||
pop {r4-r5, sl, lr}
|
||||
bx lr
|
||||
|
||||
.Lnegate_a:
|
||||
rsbs r0, r0, #0
|
||||
rsc r1, r1, #0
|
||||
bx lr
|
||||
|
||||
.Lnegate_b:
|
||||
rsbs r2, r2, #0
|
||||
rsc r3, r3, #0
|
||||
bx lr
|
||||
|
||||
.Lmaxdenom:
|
||||
/*
|
||||
* We had a carry so the denominator must have INT64_MIN
|
||||
* Also BLO and BHI never changed values so we can use
|
||||
* them to see if the numerator has the same value. We
|
||||
* don't have to worry about sign.
|
||||
*/
|
||||
teq r3, r1
|
||||
teqeq r2, r0
|
||||
bne 1f
|
||||
|
||||
/*
|
||||
* They were equal, so we return a quotient of 1 and remainder of 0.
|
||||
*/
|
||||
mov r0, #1
|
||||
mov r1, #0
|
||||
mov r2, #0
|
||||
mov r3, #0
|
||||
pop {r4-r5, sl, lr}
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* Our remainder must be the numerator and our quotient is 0.
|
||||
*/
|
||||
1: mov r2, r0
|
||||
mov r3, r1
|
||||
mov r0, #0
|
||||
mov r1, #0
|
||||
pop {r4-r5, sl, lr}
|
||||
bx lr
|
||||
80
kernel/lib/intlib.c
Normal file
80
kernel/lib/intlib.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
*
|
||||
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
* adhered to.
|
||||
*
|
||||
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
* in the code are not to be removed.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/intlib.h>
|
||||
#include "quad.h"
|
||||
|
||||
/*---------------------------
|
||||
* Integer library functions
|
||||
*---------------------------
|
||||
*/
|
||||
|
||||
/* Flags used internally to IntLDiv. */
|
||||
#define FLIP_QUOTIENT 0x00000001
|
||||
#define FLIP_REMAINDER 0x00000002
|
||||
|
||||
/*
|
||||
* Divides two 64-bit integers and returns a quotient and a remainder in a structure.
|
||||
*
|
||||
* Parameters:
|
||||
* - pResult = Pointer to an LDIV structure to contain the quotient and remainder.
|
||||
* - num = The numerator (dividend) for the division.
|
||||
* - demom = The demoninator (divisor) for the division.
|
||||
*
|
||||
* Returns:
|
||||
* Standard SUCCEEDED/FAILED HRESULT.
|
||||
*/
|
||||
HRESULT IntLDiv(PLDIV pResult, INT64 num, INT64 denom)
|
||||
{
|
||||
UINT32 mode = 0;
|
||||
if (denom == 0)
|
||||
{
|
||||
pResult->quot = pResult->rem = 0;
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if (denom < 0)
|
||||
{
|
||||
mode ^= FLIP_QUOTIENT;
|
||||
denom = -denom;
|
||||
}
|
||||
if (num < 0)
|
||||
{
|
||||
mode ^= (FLIP_QUOTIENT|FLIP_REMAINDER);
|
||||
num = -num;
|
||||
}
|
||||
pResult->quot = __qdivrem(num, denom, (PUINT64)(&(pResult->rem)));
|
||||
if (mode & FLIP_QUOTIENT)
|
||||
pResult->quot = -(pResult->quot);
|
||||
if (mode & FLIP_REMAINDER)
|
||||
pResult->rem = -(pResult->rem);
|
||||
return S_OK;
|
||||
}
|
||||
182
kernel/lib/kernel-lib.ldi
Normal file
182
kernel/lib/kernel-lib.ldi
Normal file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
*
|
||||
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
* adhered to.
|
||||
*
|
||||
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
* in the code are not to be removed.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
/* Copied from default linker script for relocatable linking under ARM & modified */
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
.interp 0 : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash 0 : { *(.hash) }
|
||||
.gnu.hash 0 : { *(.gnu.hash) }
|
||||
.dynsym 0 : { *(.dynsym) }
|
||||
.dynstr 0 : { *(.dynstr) }
|
||||
.gnu.version 0 : { *(.gnu.version) }
|
||||
.gnu.version_d 0: { *(.gnu.version_d) }
|
||||
.gnu.version_r 0: { *(.gnu.version_r) }
|
||||
.rel.init 0 : { *(.rel.init) }
|
||||
.rela.init 0 : { *(.rela.init) }
|
||||
.rel.text 0 : { *(.rel.text) }
|
||||
.rela.text 0 : { *(.rela.text) }
|
||||
.rel.fini 0 : { *(.rel.fini) }
|
||||
.rela.fini 0 : { *(.rela.fini) }
|
||||
.rel.rodata 0 : { *(.rel.rodata) }
|
||||
.rela.rodata 0 : { *(.rela.rodata) }
|
||||
.rel.ctors 0 : { *(.rel.ctors) }
|
||||
.rela.ctors 0 : { *(.rela.ctors) }
|
||||
.rel.dtors 0 : { *(.rel.dtors) }
|
||||
.rela.dtors 0 : { *(.rela.dtors) }
|
||||
.rel.got 0 : { *(.rel.got) }
|
||||
.rela.got 0 : { *(.rela.got) }
|
||||
.rel.bss 0 : { *(.rel.bss) }
|
||||
.rela.bss 0 : { *(.rela.bss) }
|
||||
.rel.iplt 0 :
|
||||
{
|
||||
*(.rel.iplt)
|
||||
}
|
||||
.rela.iplt 0 :
|
||||
{
|
||||
*(.rela.iplt)
|
||||
}
|
||||
.rel.plt 0 :
|
||||
{
|
||||
*(.rel.plt)
|
||||
}
|
||||
.rela.plt 0 :
|
||||
{
|
||||
*(.rela.plt)
|
||||
}
|
||||
.init 0 :
|
||||
{
|
||||
KEEP (*(.init))
|
||||
} =0
|
||||
.plt 0 : { *(.plt) }
|
||||
.iplt 0 : { *(.iplt) }
|
||||
.lib.text 0 :
|
||||
{
|
||||
*(.text .stub)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
} =0
|
||||
.fini 0 :
|
||||
{
|
||||
KEEP (*(.fini))
|
||||
} =0
|
||||
.lib.rodata 0 : { *(.rodata) }
|
||||
.lib.rodata1 0 : { *(.rodata1) }
|
||||
.ARM.extab 0 : { *(.ARM.extab) }
|
||||
.ARM.exidx 0 : { *(.ARM.exidx) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
.eh_frame 0 : ONLY_IF_RO { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table 0 : ONLY_IF_RO { *(.gcc_except_table
|
||||
.gcc_except_table.*) }
|
||||
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||
.exception_ranges 0 : ONLY_IF_RO { *(.exception_ranges
|
||||
.exception_ranges*) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
/* Exception handling */
|
||||
.eh_frame 0 : ONLY_IF_RW { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table 0 : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||
.exception_ranges 0 : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
|
||||
/* Thread Local Storage sections */
|
||||
.preinit_array 0 :
|
||||
{
|
||||
KEEP (*(.preinit_array))
|
||||
}
|
||||
.jcr 0 : { KEEP (*(.jcr)) }
|
||||
.dynamic 0 : { *(.dynamic) }
|
||||
.got 0 : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/* DWARF 3 */
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.stack 0 :
|
||||
{
|
||||
*(.stack)
|
||||
}
|
||||
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
|
||||
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
|
||||
|
||||
/* we don't allow data in the library section, so discard all data segments */
|
||||
/DISCARD/ : {
|
||||
*(.rel.data.rel.ro)
|
||||
*(.rela.data.rel.ro)
|
||||
*(.rel.data)
|
||||
*(.rela.data)
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
*(.rel.tdata)
|
||||
*(.rela.tdata)
|
||||
*(.rel.tbss)
|
||||
*(.rela.tbss)
|
||||
*(.tdata)
|
||||
*(.tbss)
|
||||
}
|
||||
}
|
||||
50
kernel/lib/lib_guids.c
Normal file
50
kernel/lib/lib_guids.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
*
|
||||
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
* adhered to.
|
||||
*
|
||||
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
* in the code are not to be removed.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
/*------------------------------------------------------------------------------------------------------
|
||||
* This module defines all the GUIDs as static data that goes into the library segment (i.e. accessible
|
||||
* from both supervisor and user modes). The following definitions MUST be first in this source file,
|
||||
* AND in this order.
|
||||
*------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
#include <comrogue/internals/seg.h>
|
||||
#define GUIDATTR SEG_RODATA
|
||||
#define INITGUID
|
||||
#include <comrogue/object_definition_macros.h>
|
||||
|
||||
/*-------------------------------------------------------------------------------------------------
|
||||
* Now include all the header files generated from IDL. Try to include them in the order in which
|
||||
* interfaces are defined.
|
||||
*-------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
#include <comrogue/object_types.h>
|
||||
#include <comrogue/objectbase.h>
|
||||
#include <comrogue/allocator.h>
|
||||
123
kernel/lib/objhelp.c
Normal file
123
kernel/lib/objhelp.c
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
*
|
||||
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
* adhered to.
|
||||
*
|
||||
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
* in the code are not to be removed.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/scode.h>
|
||||
#include <comrogue/str.h>
|
||||
#include <comrogue/object_types.h>
|
||||
#include <comrogue/objectbase.h>
|
||||
#include <comrogue/allocator.h>
|
||||
#include <comrogue/stdobj.h>
|
||||
#include <comrogue/objhelp.h>
|
||||
|
||||
/*--------------------------------------------
|
||||
* Standard object functions (API-type calls)
|
||||
*--------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determines whether two GUID references are equal.
|
||||
*
|
||||
* Parameters:
|
||||
* - guid1 = First GUID to compare.
|
||||
* - guid2 = Second GUID to compare.
|
||||
*
|
||||
* Returns:
|
||||
* TRUE if the GUIDs are equal, FALSE otherwise.
|
||||
*/
|
||||
BOOL IsEqualGUID(REFGUID guid1, REFGUID guid2)
|
||||
{
|
||||
return MAKEBOOL(StrCompareMem(guid1, guid2, sizeof(GUID)) == 0);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* Functions to be used in the construction of C interface vtables
|
||||
*-----------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Retrieves pointers to the supported interfaces on an object. Any pointer returned by this method
|
||||
* has AddRef called on it before it returns.
|
||||
*
|
||||
* Parameters:
|
||||
* - pThis = Base interface pointer.
|
||||
* - riid = The identifier of the interface being requested.
|
||||
* - ppvObject = Address of a pointer variable that receives the interface pointer requested by riid.
|
||||
* On return, *ppvObject contains the requested interface pointer, or NULL if the interface
|
||||
* is not supported.
|
||||
*
|
||||
* Returns:
|
||||
* - S_OK = If the interface is supported. *ppvObject contains the pointer to the interface.
|
||||
* - E_NOINTERFACE = If the interface is not supported. *ppvObject contains NULL.
|
||||
* - E_POINTER = If ppvObject is NULL.
|
||||
*/
|
||||
/* This macro makes a ObjHlpStandardQueryInterface_IXXX function for any interface directly derived from IUnknown */
|
||||
#define MAKE_BASE_QI(iface) \
|
||||
HRESULT ObjHlpStandardQueryInterface_ ## iface (IUnknown *pThis, REFIID riid, PPVOID ppvObject) \
|
||||
{ \
|
||||
if (!ppvObject) return E_POINTER; \
|
||||
*ppvObject = NULL; \
|
||||
if (!IsEqualIID(riid, &IID_ ## iface) && !IsEqualIID(riid, &IID_IUnknown)) \
|
||||
return E_NOINTERFACE; \
|
||||
IUnknown_AddRef(pThis); \
|
||||
*ppvObject = (PVOID)pThis; \
|
||||
return S_OK; \
|
||||
}
|
||||
|
||||
MAKE_BASE_QI(IMalloc)
|
||||
|
||||
/*
|
||||
* "Dummy" version of AddRef/Release used for static objects.
|
||||
*
|
||||
* Parameters:
|
||||
* - pThis = Base interface pointer.
|
||||
*
|
||||
* Returns:
|
||||
* 1.
|
||||
*/
|
||||
UINT32 ObjHlpStaticAddRefRelease(IUnknown *pThis)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Method returning void that does nothing.
|
||||
*
|
||||
* Parameters:
|
||||
* - pThis = Base interface pointer.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
void ObjHlpDoNothingReturnVoid(IUnknown *pThis)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
279
kernel/lib/qdivrem.c
Normal file
279
kernel/lib/qdivrem.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/* Derived from FreeBSD libkern qdivrem.c, munged by Erbo to COMROGUE standards */
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/internals/seg.h>
|
||||
#include "quad.h"
|
||||
|
||||
/*
|
||||
* Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
|
||||
* section 4.3.1, pp. 257--259.
|
||||
*/
|
||||
|
||||
#define B (1 << HALF_BITS) /* digit base */
|
||||
|
||||
/* Combine two `digits' to make a single two-digit number. */
|
||||
#define COMBINE(a, b) (((UINT32)(a) << HALF_BITS) | (b))
|
||||
|
||||
/* select a type for digits in base B: use unsigned short if they fit */
|
||||
typedef UINT16 DIGIT;
|
||||
|
||||
/*
|
||||
* Shift p[0]..p[len] left `sh' bits, ignoring any bits that
|
||||
* `fall out' the left (there never will be any such anyway).
|
||||
* We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
|
||||
*/
|
||||
static void __shl(register DIGIT *p, register INT32 len, register INT32 sh)
|
||||
{
|
||||
register INT32 i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
|
||||
p[i] = LHALF(p[i] << sh);
|
||||
}
|
||||
|
||||
/*
|
||||
* __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
|
||||
*
|
||||
* We do this in base 2^HALF_BITS, so that all intermediate products
|
||||
* fit within u_long. As a consequence, the maximum length dividend and
|
||||
* divisor are 4 `digits' in this base (they are shorter if they have
|
||||
* leading zeros).
|
||||
*/
|
||||
UINT64 __qdivrem(UINT64 uq, UINT64 vq, PUINT64 pRem)
|
||||
{
|
||||
UU tmp;
|
||||
DIGIT *u, *v, *q;
|
||||
register DIGIT v1, v2;
|
||||
UINT32 qhat, rhat, t;
|
||||
INT32 m, n, d, j, i;
|
||||
DIGIT uspace[5], vspace[5], qspace[5];
|
||||
|
||||
/*
|
||||
* Take care of special cases: divide by zero, and u < v.
|
||||
*/
|
||||
if (vq == 0)
|
||||
{ /* divide by zero. */
|
||||
SEG_RODATA static volatile const unsigned int zero = 0;
|
||||
|
||||
tmp.ul[H] = tmp.ul[L] = 1 / zero;
|
||||
if (pRem)
|
||||
*pRem = uq;
|
||||
return tmp.q;
|
||||
}
|
||||
if (uq < vq)
|
||||
{
|
||||
if (pRem)
|
||||
*pRem = uq;
|
||||
return 0;
|
||||
}
|
||||
u = uspace;
|
||||
v = vspace;
|
||||
q = qspace;
|
||||
|
||||
/*
|
||||
* Break dividend and divisor into digits in base B, then
|
||||
* count leading zeros to determine m and n. When done, we
|
||||
* will have:
|
||||
* u = (u[1]u[2]...u[m+n]) sub B
|
||||
* v = (v[1]v[2]...v[n]) sub B
|
||||
* v[1] != 0
|
||||
* 1 < n <= 4 (if n = 1, we use a different division algorithm)
|
||||
* m >= 0 (otherwise u < v, which we already checked)
|
||||
* m + n = 4
|
||||
* and thus
|
||||
* m = 4 - n <= 2
|
||||
*/
|
||||
tmp.uq = uq;
|
||||
u[0] = 0;
|
||||
u[1] = HHALF(tmp.ul[H]);
|
||||
u[2] = LHALF(tmp.ul[H]);
|
||||
u[3] = HHALF(tmp.ul[L]);
|
||||
u[4] = LHALF(tmp.ul[L]);
|
||||
tmp.uq = vq;
|
||||
v[1] = HHALF(tmp.ul[H]);
|
||||
v[2] = LHALF(tmp.ul[H]);
|
||||
v[3] = HHALF(tmp.ul[L]);
|
||||
v[4] = LHALF(tmp.ul[L]);
|
||||
for (n = 4; v[1] == 0; v++)
|
||||
{
|
||||
if (--n == 1)
|
||||
{
|
||||
UINT32 rbj; /* r*B+u[j] (not root boy jim) */
|
||||
DIGIT q1, q2, q3, q4;
|
||||
|
||||
/*
|
||||
* Change of plan, per exercise 16.
|
||||
* r = 0;
|
||||
* for j = 1..4:
|
||||
* q[j] = floor((r*B + u[j]) / v),
|
||||
* r = (r*B + u[j]) % v;
|
||||
* We unroll this completely here.
|
||||
*/
|
||||
t = v[2]; /* nonzero, by definition */
|
||||
q1 = u[1] / t;
|
||||
rbj = COMBINE(u[1] % t, u[2]);
|
||||
q2 = rbj / t;
|
||||
rbj = COMBINE(rbj % t, u[3]);
|
||||
q3 = rbj / t;
|
||||
rbj = COMBINE(rbj % t, u[4]);
|
||||
q4 = rbj / t;
|
||||
if (pRem)
|
||||
*pRem = rbj % t;
|
||||
tmp.ul[H] = COMBINE(q1, q2);
|
||||
tmp.ul[L] = COMBINE(q3, q4);
|
||||
return tmp.q;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* By adjusting q once we determine m, we can guarantee that
|
||||
* there is a complete four-digit quotient at &qspace[1] when
|
||||
* we finally stop.
|
||||
*/
|
||||
for (m = 4 - n; u[1] == 0; u++)
|
||||
m--;
|
||||
for (i = 4 - m; --i >= 0;)
|
||||
q[i] = 0;
|
||||
q += 4 - m;
|
||||
|
||||
/*
|
||||
* Here we run Program D, translated from MIX to C and acquiring
|
||||
* a few minor changes.
|
||||
*
|
||||
* D1: choose multiplier 1 << d to ensure v[1] >= B/2.
|
||||
*/
|
||||
d = 0;
|
||||
for (t = v[1]; t < B / 2; t <<= 1)
|
||||
d++;
|
||||
if (d > 0)
|
||||
{
|
||||
__shl(u, m + n, d); /* u <<= d */
|
||||
__shl(v + 1, n - 1, d); /* v <<= d */
|
||||
}
|
||||
/*
|
||||
* D2: j = 0.
|
||||
*/
|
||||
j = 0;
|
||||
v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
|
||||
v2 = v[2]; /* for D3 */
|
||||
do
|
||||
{
|
||||
register DIGIT uj0, uj1, uj2;
|
||||
|
||||
/*
|
||||
* D3: Calculate qhat (\^q, in TeX notation).
|
||||
* Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
|
||||
* let rhat = (u[j]*B + u[j+1]) mod v[1].
|
||||
* While rhat < B and v[2]*qhat > rhat*B+u[j+2],
|
||||
* decrement qhat and increase rhat correspondingly.
|
||||
* Note that if rhat >= B, v[2]*qhat < rhat*B.
|
||||
*/
|
||||
uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
|
||||
uj1 = u[j + 1]; /* for D3 only */
|
||||
uj2 = u[j + 2]; /* for D3 only */
|
||||
if (uj0 == v1)
|
||||
{
|
||||
qhat = B;
|
||||
rhat = uj1;
|
||||
goto qhat_too_big;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 nn = COMBINE(uj0, uj1);
|
||||
qhat = nn / v1;
|
||||
rhat = nn % v1;
|
||||
}
|
||||
while (v2 * qhat > COMBINE(rhat, uj2))
|
||||
{
|
||||
qhat_too_big:
|
||||
qhat--;
|
||||
if ((rhat += v1) >= B)
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* D4: Multiply and subtract.
|
||||
* The variable `t' holds any borrows across the loop.
|
||||
* We split this up so that we do not require v[0] = 0,
|
||||
* and to eliminate a final special case.
|
||||
*/
|
||||
for (t = 0, i = n; i > 0; i--)
|
||||
{
|
||||
t = u[i + j] - v[i] * qhat - t;
|
||||
u[i + j] = LHALF(t);
|
||||
t = (B - HHALF(t)) & (B - 1);
|
||||
}
|
||||
t = u[j] - t;
|
||||
u[j] = LHALF(t);
|
||||
/*
|
||||
* D5: test remainder.
|
||||
* There is a borrow if and only if HHALF(t) is nonzero;
|
||||
* in that (rare) case, qhat was too large (by exactly 1).
|
||||
* Fix it by adding v[1..n] to u[j..j+n].
|
||||
*/
|
||||
if (HHALF(t))
|
||||
{
|
||||
qhat--;
|
||||
for (t = 0, i = n; i > 0; i--)
|
||||
{ /* D6: add back. */
|
||||
t += u[i + j] + v[i];
|
||||
u[i + j] = LHALF(t);
|
||||
t = HHALF(t);
|
||||
}
|
||||
u[j] = LHALF(u[j] + t);
|
||||
}
|
||||
q[j] = qhat;
|
||||
} while (++j <= m); /* D7: loop on j. */
|
||||
|
||||
/*
|
||||
* If caller wants the remainder, we have to calculate it as
|
||||
* u[m..m+n] >> d (this is at most n digits and thus fits in
|
||||
* u[m+1..m+n], but we may need more source digits).
|
||||
*/
|
||||
if (pRem)
|
||||
{
|
||||
if (d)
|
||||
{
|
||||
for (i = m + n; i > m; --i)
|
||||
u[i] = (u[i] >> d) | LHALF(u[i - 1] << (HALF_BITS - d));
|
||||
u[i] = 0;
|
||||
}
|
||||
tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
|
||||
tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
|
||||
*pRem = tmp.q;
|
||||
}
|
||||
|
||||
tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
|
||||
tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
|
||||
return tmp.q;
|
||||
}
|
||||
71
kernel/lib/quad.h
Normal file
71
kernel/lib/quad.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*-
|
||||
* Copyright (c) 1992, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This software was developed by the Computer Systems Engineering group
|
||||
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
|
||||
* contributed to Berkeley.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)quad.h 8.1 (Berkeley) 6/4/93
|
||||
* $FreeBSD$
|
||||
*/
|
||||
/* Derived from FreeBDS libkern quad.h, munged by Erbo to COMROGUE standards */
|
||||
#ifndef QUAD_H_INCLUDED
|
||||
#define QUAD_H_INCLUDED
|
||||
|
||||
#include <comrogue/types.h>
|
||||
|
||||
typedef union tagUU {
|
||||
INT64 q; /* signed quad */
|
||||
UINT64 uq; /* unsigned quad */
|
||||
INT32 sl[2]; /* two signed longs */
|
||||
UINT32 ul[2]; /* two unsigned longs */
|
||||
} UU;
|
||||
|
||||
/* Low word/high word definitions. */
|
||||
#define L 0
|
||||
#define H 1
|
||||
|
||||
/* Number of bits in a halfword. */
|
||||
#define HALF_BITS (INT32_BITS / 2)
|
||||
|
||||
/*
|
||||
* Extract high and low shortwords from longword, and move low shortword of
|
||||
* longword to upper half of long, i.e., produce the upper longword of
|
||||
* ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.)
|
||||
*
|
||||
* These are used in the multiply code, to split a longword into upper
|
||||
* and lower halves, and to reassemble a product as a quad_t, shifted left
|
||||
* (sizeof(long)*CHAR_BIT/2).
|
||||
*/
|
||||
#define HHALF(x) ((x) >> HALF_BITS)
|
||||
#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1))
|
||||
#define LHUP(x) ((x) << HALF_BITS)
|
||||
|
||||
extern UINT64 __qdivrem(UINT64 u, UINT64 v, PUINT64 pRem);
|
||||
|
||||
#endif /* QUAD_H_INCLUDED */
|
||||
519
kernel/lib/rbtree.c
Normal file
519
kernel/lib/rbtree.c
Normal file
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
*
|
||||
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
* adhered to.
|
||||
*
|
||||
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
* in the code are not to be removed.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/internals/rbtree.h>
|
||||
#include <comrogue/internals/trace.h>
|
||||
|
||||
#ifdef THIS_FILE
|
||||
#undef THIS_FILE
|
||||
DECLARE_THIS_FILE
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------------------------------
|
||||
* An implementation of left-leaning red-black 2-3 trees as detailed in "Left-leaning Red-Black Trees,"
|
||||
* Robert Sedgwick, Princeton University, 2008 (http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf).
|
||||
* See also Java source at https://gist.github.com/741080.
|
||||
*
|
||||
* Note that we store the node color as a single bit in the low-order bit of the "right" node pointer.
|
||||
* This is do-able since, for all cases, pointers to instances of RBTREENODE will be 4-byte aligned.
|
||||
*------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* A standard compare-by-value function for tree keys, which compares the numeric values of the keys as
|
||||
* unsigned integers.
|
||||
*
|
||||
* Parameters:
|
||||
* - k1 = First key value to compare.
|
||||
* - k2 = Second key value to compare.
|
||||
*
|
||||
* Returns:
|
||||
* 0 if the keys are equal; an integer less than 0 if k1 is less than k2; an integer greater than 0 if
|
||||
* k1 is greater than k2.
|
||||
*/
|
||||
INT32 RbtStdCompareByValue(TREEKEY k1, TREEKEY k2)
|
||||
{
|
||||
if (k1 == k2)
|
||||
return 0;
|
||||
if (((UINT_PTR)k1) < ((UINT_PTR)k2))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotates a subtree "leftward," so that the root node of the tree is the former root node's right child.
|
||||
* The new root node inherits the former root node's color, and the former root node turns red.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to the root node of the subtree.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the new root node of the subtree after the rotation.
|
||||
*/
|
||||
static PRBTREENODE rotate_left(PRBTREENODE ptn)
|
||||
{
|
||||
register PRBTREENODE ptnNewRoot = rbtNodeRight(ptn);
|
||||
ASSERT(ptnNewRoot);
|
||||
rbtSetNodeRight(ptn, ptnNewRoot->ptnLeft);
|
||||
ptnNewRoot->ptnLeft = ptn;
|
||||
rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn));
|
||||
rbtSetNodeColor(ptn, RED);
|
||||
return ptnNewRoot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rotates a subtree "rightward," so that the root node of the tree is the former root node's left child.
|
||||
* The new root node inherits the former root node's color, and the former root node turns red.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to the root node of the subtree.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the new root node of the subtree after the rotation.
|
||||
*/
|
||||
static PRBTREENODE rotate_right(PRBTREENODE ptn)
|
||||
{
|
||||
register PRBTREENODE ptnNewRoot = ptn->ptnLeft;
|
||||
ASSERT(ptnNewRoot);
|
||||
ptn->ptnLeft = rbtNodeRight(ptnNewRoot);
|
||||
rbtSetNodeRight(ptnNewRoot, ptn);
|
||||
rbtSetNodeColor(ptnNewRoot, rbtNodeColor(ptn));
|
||||
rbtSetNodeColor(ptn, RED);
|
||||
return ptnNewRoot;
|
||||
}
|
||||
|
||||
/*
|
||||
* Flips the color of the specified node and both its immediate children.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to the node to be color-flipped.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
static void color_flip(PRBTREENODE ptn)
|
||||
{
|
||||
rbtToggleColor(ptn);
|
||||
rbtToggleColor(ptn->ptnLeft);
|
||||
rbtToggleColor(rbtNodeRight(ptn));
|
||||
}
|
||||
|
||||
/*
|
||||
* Fixes up the given subtree after an insertion or deletion, to ensure that it maintains the invariants
|
||||
* that no two consecutive links in the tree may be red, and that all red links must lean left.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to the root node of the subtree to be fixed up.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the new root node of the subtree after fixup is performed.
|
||||
*/
|
||||
static PRBTREENODE fix_up(PRBTREENODE ptn)
|
||||
{
|
||||
if (rbtIsRed(rbtNodeRight(ptn)) && !rbtIsRed(ptn->ptnLeft))
|
||||
ptn = rotate_left(ptn);
|
||||
if (rbtIsRed(ptn->ptnLeft) && rbtIsRed(ptn->ptnLeft->ptnLeft))
|
||||
ptn = rotate_right(ptn);
|
||||
if (rbtIsRed(ptn->ptnLeft) && rbtIsRed(rbtNodeRight(ptn)))
|
||||
color_flip(ptn);
|
||||
return ptn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inserts a new node under the current subtree. An O(log n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure, containing the compare function.
|
||||
* - ptnCurrent = Pointer to the current subtree we're inserting into.
|
||||
* - ptnNew = Pointer to the new tree node to be inserted. This node must have been initialized with
|
||||
* the rbtInitNode macro to contain a key, NULL left and right pointers, and be red. It is
|
||||
* assumed that the node's key does NOT already exist in the tree.
|
||||
*
|
||||
* Returns:
|
||||
* The pointer to the new subtree after the insertion is performed.
|
||||
*
|
||||
* N.B.:
|
||||
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
|
||||
* by its stack frames will be O(log n).
|
||||
*/
|
||||
static PRBTREENODE insert_under(PRBTREE ptree, PRBTREENODE ptnCurrent, PRBTREENODE ptnNew)
|
||||
{
|
||||
register int cmp; /* compare result */
|
||||
|
||||
if (!ptnCurrent)
|
||||
return ptnNew; /* degenerate case */
|
||||
cmp = (*(ptree->pfnTreeCompare))(ptnNew->treekey, ptnCurrent->treekey);
|
||||
ASSERT(cmp != 0);
|
||||
if (cmp < 0)
|
||||
ptnCurrent->ptnLeft = insert_under(ptree, ptnCurrent->ptnLeft, ptnNew);
|
||||
else
|
||||
rbtSetNodeRight(ptnCurrent, insert_under(ptree, rbtNodeRight(ptnCurrent), ptnNew));
|
||||
return fix_up(ptnCurrent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inserts a new node into the tree. An O(log n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
* - ptnNew = Pointer to the new tree node to be inserted. This node must have been initialized with
|
||||
* the rbtInitNode macro to contain a key, NULL left and right pointers, and be red. It is
|
||||
* assumed that the node's key does NOT already exist in the tree.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
void RbtInsert(PRBTREE ptree, PRBTREENODE ptnNew)
|
||||
{
|
||||
ptree->ptnRoot = insert_under(ptree, ptree->ptnRoot, ptnNew);
|
||||
rbtSetNodeColor(ptree->ptnRoot, BLACK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locates a node in the tree by key. An O(log n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
* - key = Key value to be looked up.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the node where the key is found, or NULL if not found.
|
||||
*/
|
||||
PRBTREENODE RbtFind(PRBTREE ptree, TREEKEY key)
|
||||
{
|
||||
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
||||
register int cmp; /* compare result */
|
||||
|
||||
while (ptn)
|
||||
{
|
||||
cmp = (*(ptree->pfnTreeCompare))(key, ptn->treekey);
|
||||
if (cmp == 0)
|
||||
break; /* found */
|
||||
else if (cmp < 0)
|
||||
ptn = ptn->ptnLeft;
|
||||
else
|
||||
ptn = rbtNodeRight(ptn);
|
||||
}
|
||||
|
||||
return ptn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a key, returns either the node that matches the key, if the key is in the tree, or the node
|
||||
* that has a key that most immediately precedes the supplied key. An O(log n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
* - key = Key value to be looked up.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the node where the key is found, or pointer to the predecessor node, or NULL if the key
|
||||
* is less than every key in the tree and hence has no predecessor.
|
||||
*/
|
||||
PRBTREENODE RbtFindPredecessor(PRBTREE ptree, TREEKEY key)
|
||||
{
|
||||
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
||||
register int cmp; /* compare result */
|
||||
|
||||
while (ptn)
|
||||
{
|
||||
cmp = (*(ptree->pfnTreeCompare))(key, ptn->treekey);
|
||||
if (cmp == 0)
|
||||
break; /* found */
|
||||
else if (cmp > 0)
|
||||
{
|
||||
if (rbtNodeRight(ptn))
|
||||
ptn = rbtNodeRight(ptn);
|
||||
else
|
||||
break; /* found predecessor */
|
||||
}
|
||||
else
|
||||
ptn = ptn->ptnLeft;
|
||||
}
|
||||
return ptn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a key, returns either the node that matches the key, if the key is in the tree, or the node
|
||||
* that has a key that most immediately succeeds the supplied key. An O(log n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
* - key = Key value to be looked up.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the node where the key is found, or pointer to the successor node, or NULL if the key
|
||||
* is greater than every key in the tree and hence has no successor.
|
||||
*/
|
||||
PRBTREENODE RbtFindSuccessor(PRBTREE ptree, TREEKEY key)
|
||||
{
|
||||
register PRBTREENODE ptn = ptree->ptnRoot; /* current node */
|
||||
register int cmp; /* compare result */
|
||||
|
||||
while (ptn)
|
||||
{
|
||||
cmp = (*(ptree->pfnTreeCompare))(key, ptn->treekey);
|
||||
if (cmp == 0)
|
||||
break; /* found */
|
||||
else if (cmp < 0)
|
||||
{
|
||||
if (ptn->ptnLeft)
|
||||
ptn = ptn->ptnLeft;
|
||||
else
|
||||
break; /* found successor */
|
||||
}
|
||||
else
|
||||
ptn = rbtNodeRight(ptn);
|
||||
}
|
||||
return ptn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the "minimum" node in the subtree (the one at the bottom end of the left spine of the subtree).
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to the subtree to be searched.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the leftmost node in the subtree.
|
||||
*/
|
||||
static PRBTREENODE find_min(PRBTREENODE ptn)
|
||||
{
|
||||
while (ptn->ptnLeft)
|
||||
ptn = ptn->ptnLeft;
|
||||
return ptn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds the "minimum" node in the tree (the one at the bottom end of the left spine of the tree).
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the leftmost node in the tree. If the tree has no nodes, NULL is returned.
|
||||
*/
|
||||
PRBTREENODE RbtFindMin(PRBTREE ptree)
|
||||
{
|
||||
return ptree->ptnRoot ? find_min(ptree->ptnRoot) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fixup required to delete the leftmost node; we maintain the invariant that either the current node
|
||||
* or its left child is red. After a color flip, we resolve any successive reds on the right with rotations
|
||||
* and another color flip.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to root of subtree to be fixed up.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to root of subtree after fixup.
|
||||
*/
|
||||
static PRBTREENODE move_red_left(PRBTREENODE ptn)
|
||||
{
|
||||
color_flip(ptn);
|
||||
if (rbtNodeRight(ptn) && rbtIsRed(rbtNodeRight(ptn)->ptnLeft))
|
||||
{
|
||||
rbtSetNodeRight(ptn, rotate_right(rbtNodeRight(ptn)));
|
||||
ptn = rotate_left(ptn);
|
||||
color_flip(ptn);
|
||||
}
|
||||
return ptn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fixup required to delete an internal node, rotating left-leaning red links to the right.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to root of subtree to be fixed up.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to root of subtree after fixup.
|
||||
*/
|
||||
static PRBTREENODE move_red_right(PRBTREENODE ptn)
|
||||
{
|
||||
color_flip(ptn);
|
||||
if (ptn->ptnLeft && rbtIsRed(ptn->ptnLeft->ptnLeft))
|
||||
{
|
||||
ptn = rotate_right(ptn);
|
||||
color_flip(ptn);
|
||||
}
|
||||
return ptn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes the leftmost node in the subtree. (Note that "deletes" means "removes from the tree." No memory
|
||||
* delete operation is actually performed.)
|
||||
*
|
||||
* Parameters:
|
||||
* - ptn = Pointer to root of subtree to have its leftmost node deleted.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to root of subtree after having the leftmost node deleted.
|
||||
*
|
||||
* N.B.:
|
||||
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
|
||||
* by its stack frames will be O(log n).
|
||||
*/
|
||||
static PRBTREENODE delete_min(PRBTREENODE ptn)
|
||||
{
|
||||
if (!(ptn->ptnLeft))
|
||||
return rbtNodeRight(ptn);
|
||||
if (!rbtIsRed(ptn->ptnLeft) && !rbtIsRed(ptn->ptnLeft->ptnLeft))
|
||||
ptn = move_red_left(ptn);
|
||||
ptn->ptnLeft = delete_min(ptn->ptnLeft);
|
||||
return fix_up(ptn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes the node in the subtree having an arbitrary key. (Note that "deletes" means "removes from the tree."
|
||||
* No memory delete operation is actually performed.) An O(log n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure, containing the compare function.
|
||||
* - ptnCurrent = Pointer to the root of the current subtree we're deleting from.
|
||||
* - key = Key value we're deleting from the tree. It is assumed that this key value exists in the subtree.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the root of the subtree after the node has been deleted.
|
||||
*
|
||||
* N.B.:
|
||||
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
|
||||
* by its stack frames (and those of delete_min, where we call it) will be O(log n).
|
||||
*/
|
||||
static PRBTREENODE delete_from_under(PRBTREE ptree, PRBTREENODE ptnCurrent, TREEKEY key)
|
||||
{
|
||||
register int cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
|
||||
if (cmp < 0)
|
||||
{
|
||||
/* hunt down the left subtree */
|
||||
if (!rbtIsRed(ptnCurrent->ptnLeft) && !rbtIsRed(ptnCurrent->ptnLeft->ptnLeft))
|
||||
ptnCurrent = move_red_left(ptnCurrent);
|
||||
ptnCurrent->ptnLeft = delete_from_under(ptree, ptnCurrent->ptnLeft, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rbtIsRed(ptnCurrent->ptnLeft))
|
||||
{
|
||||
ptnCurrent = rotate_right(ptnCurrent);
|
||||
cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
|
||||
}
|
||||
if ((cmp == 0) && !rbtNodeRight(ptnCurrent))
|
||||
return ptnCurrent->ptnLeft; /* degenerate case */
|
||||
if ( !rbtIsRed(rbtNodeRight(ptnCurrent))
|
||||
&& (!rbtNodeRight(ptnCurrent) || !rbtIsRed(rbtNodeRight(ptnCurrent)->ptnLeft)))
|
||||
{
|
||||
ptnCurrent = move_red_right(ptnCurrent);
|
||||
cmp = (*(ptree->pfnTreeCompare))(key, ptnCurrent->treekey);
|
||||
}
|
||||
if (cmp == 0)
|
||||
{
|
||||
/*
|
||||
* Here we find the minimum node in the right subtree, unlink it, and link it into place in place of
|
||||
* ptnCurrent (i.e. node pointed to by ptnCurrent should no longer be referenced). We inherit the
|
||||
* child pointers and color of ptnCurrent (minus the reference from the right-hand tree where applicable).
|
||||
*/
|
||||
register PRBTREENODE ptnMin = find_min(rbtNodeRight(ptnCurrent));
|
||||
rbtSetNodeRight(ptnMin, delete_min(rbtNodeRight(ptnCurrent)));
|
||||
ptnMin->ptnLeft = ptnCurrent->ptnLeft;
|
||||
rbtSetNodeColor(ptnMin, rbtNodeColor(ptnCurrent));
|
||||
ptnCurrent = ptnMin;
|
||||
}
|
||||
else /* hunt down the right subtree */
|
||||
rbtSetNodeRight(ptnCurrent, delete_from_under(ptree, rbtNodeRight(ptnCurrent), key));
|
||||
}
|
||||
return fix_up(ptnCurrent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes the node in the tree having an arbitrary key. (Note that "deletes" means "removes from the tree."
|
||||
* No memory delete operation is actually performed.) An O(log n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
* - key = Key value we're deleting from the tree. It is assumed that this key value exists in the subtree.
|
||||
*
|
||||
* Returns:
|
||||
* Nothing.
|
||||
*/
|
||||
void RbtDelete(PRBTREE ptree, TREEKEY key)
|
||||
{
|
||||
ptree->ptnRoot = delete_from_under(ptree, ptree->ptnRoot, key);
|
||||
if (ptree->ptnRoot)
|
||||
rbtSetNodeColor(ptree->ptnRoot, BLACK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs an inorder traversal of the tree rooted at the specified node. An O(n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
* - ptn = Pointer to the root of the current tree node.
|
||||
* - pfnWalk = Pointer to a function called for each tree node we encounter. This function returns TRUE
|
||||
* to continue the traversal or FALSE to stop it.
|
||||
* - pData = Arbitrary data pointer that gets passed to the pfnWalk function.
|
||||
*
|
||||
* Returns:
|
||||
* TRUE if the tree was entirely traversed, FALSE if the tree walk was interrupted.
|
||||
*
|
||||
* N.B.:
|
||||
* This function is recursive; however, the nature of the tree guarantees that the stack space consumed
|
||||
* by its stack frames will be O(log n).
|
||||
*/
|
||||
static BOOL do_walk(PRBTREE ptree, PRBTREENODE ptn, PFNRBTWALK pfnWalk, PVOID pData)
|
||||
{
|
||||
register BOOL rc = TRUE;
|
||||
if (ptn->ptnLeft)
|
||||
rc = do_walk(ptree, ptn->ptnLeft, pfnWalk, pData);
|
||||
if (rc)
|
||||
rc = (*pfnWalk)(ptree, ptn, pData);
|
||||
if (rc && rbtNodeRight(ptn))
|
||||
rc = do_walk(ptree, rbtNodeRight(ptn), pfnWalk, pData);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs an inorder traversal of the tree. An O(n) operation.
|
||||
*
|
||||
* Parameters:
|
||||
* - ptree = Pointer to the tree head structure.
|
||||
* - pfnWalk = Pointer to a function called for each tree node we encounter. This function returns TRUE
|
||||
* to continue the traversal or FALSE to stop it.
|
||||
* - pData = Arbitrary data pointer that gets passed to the pfnWalk function.
|
||||
*
|
||||
* Returns:
|
||||
* TRUE if the tree was entirely traversed, FALSE if the tree walk was interrupted.
|
||||
*/
|
||||
BOOL RbtWalk(PRBTREE ptree, PFNRBTWALK pfnWalk, PVOID pData)
|
||||
{
|
||||
return (ptree->ptnRoot ? do_walk(ptree, ptree->ptnRoot, pfnWalk, pData) : TRUE);
|
||||
}
|
||||
422
kernel/lib/str.c
Normal file
422
kernel/lib/str.c
Normal file
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
* This file is part of the COMROGUE Operating System for Raspberry Pi
|
||||
*
|
||||
* Copyright (c) 2013, Eric J. Bowersox / Erbosoft Enterprises
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free for commercial and non-commercial use as long as the following conditions are
|
||||
* adhered to.
|
||||
*
|
||||
* Copyright in this file remains Eric J. Bowersox and/or Erbosoft, and as such any copyright notices
|
||||
* in the code are not to be removed.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||
* the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
|
||||
* the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* "Raspberry Pi" is a trademark of the Raspberry Pi Foundation.
|
||||
*/
|
||||
#include <comrogue/types.h>
|
||||
#include <comrogue/scode.h>
|
||||
#include <comrogue/intlib.h>
|
||||
#include <comrogue/str.h>
|
||||
#include <comrogue/internals/seg.h>
|
||||
|
||||
/*-------------------------
|
||||
* Basic string operations
|
||||
*-------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Returns whether or not the character is a digit (0-9).
|
||||
*
|
||||
* Parameters:
|
||||
* - ch = Character to be tested.
|
||||
*
|
||||
* Returns:
|
||||
* TRUE if the character is a digit, FALSE otherwise.
|
||||
*/
|
||||
BOOL StrIsDigit8(CHAR ch)
|
||||
{
|
||||
/* TODO: replace with something nicer later */
|
||||
return MAKEBOOL((ch >= '0') && (ch <= '9'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of a null-terminated string.
|
||||
*
|
||||
* Parameters:
|
||||
* - psz = The string to get the length of.
|
||||
*
|
||||
* Returns:
|
||||
* The length of the string in characters.
|
||||
*/
|
||||
INT32 StrLength8(PCSTR psz)
|
||||
{
|
||||
register PCSTR p = psz;
|
||||
while (*p)
|
||||
p++;
|
||||
return (INT32)(p - psz);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locates a character within a null-terminated string.
|
||||
*
|
||||
* Parameters:
|
||||
* - psz = String to search through for character.
|
||||
* - ch = Character to look for.
|
||||
*
|
||||
* Returns:
|
||||
* NULL if character was not found, otherwise pointer to character within string.
|
||||
*/
|
||||
PCHAR StrChar8(PCSTR psz, INT32 ch)
|
||||
{
|
||||
const CHAR mych = ch;
|
||||
for (; *psz; psz++)
|
||||
if (*psz == mych)
|
||||
return (PCHAR)psz;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*-------------------------------
|
||||
* Numeric-to-string conversions
|
||||
*-------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
* Formats an unsigned numeric value into a buffer. This function formats the value into the END of the
|
||||
* buffer and returns a pointer to the first character of the number. Note that the string-converted number
|
||||
* is NOT null-terminated!
|
||||
*
|
||||
* Parameters:
|
||||
* - value = The value to be converted.
|
||||
* - pchBuf = Pointer to the buffer in which to store the converted value.
|
||||
* - nBytes = Number of characters in the buffer.
|
||||
* - nBase = The numeric base to use to output the number. Valid values are in the interval [2,36].
|
||||
* - fUppercase = TRUE to use upper-case letters as digits in output, FALSE to use lower-case letters.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the first digit of the converted value, which will be somewhere in the interval
|
||||
* [pchBuf, pchBuf + nBytes).
|
||||
*/
|
||||
static PCHAR convert_number_engine8(UINT64 value, PCHAR pchBuf, INT32 nBytes, INT32 nBase, BOOL fUppercase)
|
||||
{
|
||||
static DECLARE_STRING8_CONST(szDigitsUppercase, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
static DECLARE_STRING8_CONST(szDigitsLowercase, "0123456789abcdefghijklmnopqrstuvwxyz");
|
||||
PCSTR pszDigits = (fUppercase ? szDigitsUppercase : szDigitsLowercase); /* digit set to use */
|
||||
PCHAR p = pchBuf + nBytes; /* output pointer */
|
||||
INT64 accumulator; /* accumulator of quotients */
|
||||
LDIV ldiv; /* buffer for division */
|
||||
|
||||
/* do initial division to get rid of high-order bit & handle 0 */
|
||||
*--p = pszDigits[value % nBase];
|
||||
accumulator = (INT64)(value / nBase);
|
||||
|
||||
while ((p > pchBuf) && (accumulator > 0))
|
||||
{ /* output digits */
|
||||
IntLDiv(&ldiv, accumulator, nBase);
|
||||
*--p = pszDigits[ldiv.rem];
|
||||
accumulator = ldiv.quot;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*-----------------------------------------
|
||||
* StrFormatV8 and its support definitions
|
||||
*-----------------------------------------
|
||||
*/
|
||||
|
||||
/* Flag values for conversion characters */
|
||||
#define FLAG_LEFTJUST 0x01 /* left-justify output field */
|
||||
#define FLAG_PLUSSIGN 0x02 /* use a '+' for the sign if >= 0 */
|
||||
#define FLAG_SPACESIGN 0x04 /* use a space for the sign if >= 0 */
|
||||
#define FLAG_ALTMODE 0x08 /* alternate conversion mode */
|
||||
#define FLAG_ZEROPAD 0x10 /* zero-pad to width */
|
||||
|
||||
/* Macro that calls the output function and either updates total output or exits */
|
||||
#define do_output(pBuf, nChr) \
|
||||
do { if ((nChr) > 0) { if (SUCCEEDED((*pfnFormat)(&pArg, (pBuf), (nChr)))) nTotalOutput += (nChr); \
|
||||
else { errorFlag = SEVERITY_ERROR; goto error; } } } while (0)
|
||||
|
||||
/* Strings used for padding */
|
||||
static DECLARE_STRING8_CONST(szPadSpace, " ");
|
||||
static DECLARE_STRING8_CONST(szPadZero, "0000000000000000000000000000000000000000000000000000000000");
|
||||
|
||||
#define PAD_SIZE (sizeof(szPadSpace) - 1) /* number of characters available in pad string */
|
||||
|
||||
/* Macro that outputs characters for padding */
|
||||
#define do_pad_output(szPad, nChr) \
|
||||
do { int n, nt = (nChr); while (nt > 0) { n = intMin(nt, PAD_SIZE); do_output(szPad, n); nt -= n; } } while (0)
|
||||
|
||||
#define MAX_VAL 509 /* maximum field value for conversion */
|
||||
#define BUFSIZE 64 /* buffer size on stack for conversion */
|
||||
#define NUM_CONVERT_BYTES 32 /* maximum number of bytes for converting a numeric value */
|
||||
|
||||
/*
|
||||
* Format a series of arguments like "printf," calling a function to perform the actual character output.
|
||||
*
|
||||
* Parameters:
|
||||
* - pfnFormat = Pointer to the format function
|
||||
* - pArg = Pointer argument passed to the format function, which may modify it
|
||||
* - pszFormat = Format string, like a printf format string.
|
||||
* - pargs = Pointer to varargs-style function arguments.
|
||||
*
|
||||
* Returns:
|
||||
* A HRESULT as follows: Severity indicates whether the output function failed or succeeded, facility is always
|
||||
* FACILITY_STRFORMAT, code indicates the number of characters output.
|
||||
*
|
||||
* Notes:
|
||||
* Floating-point conversion formats are not supported at this time.
|
||||
*/
|
||||
HRESULT StrFormatV8(PFNFORMAT8 pfnFormat, PVOID pArg, PCSTR pszFormat, va_list pargs)
|
||||
{
|
||||
static DECLARE_STRING8_CONST(szFlagChars, "0+- #"); /* flag characters and values */
|
||||
static const UINT32 SEG_RODATA auiFlagValues[] =
|
||||
{ FLAG_ZEROPAD, FLAG_LEFTJUST, FLAG_PLUSSIGN, FLAG_SPACESIGN, FLAG_ALTMODE, 0 };
|
||||
static DECLARE_STRING8_CONST(szConversionChars, "hl"); /* conversion characters */
|
||||
PCSTR p; /* pointer used to walk the format string */
|
||||
PCHAR pFlag; /* pointer to flag character/temp buffer pointer */
|
||||
PCHAR pchOutput; /* pointer to characters actually output */
|
||||
INT32 nchOutput; /* number of characters output */
|
||||
PCHAR pchPrefix; /* pointer to prefix characters */
|
||||
INT32 nchPrefix; /* number of prefix characters */
|
||||
INT32 nchZeroPrefix; /* number of zeroes to write as a prefix */
|
||||
INT32 nTotalOutput = 0; /* total number of characters output */
|
||||
UINT32 errorFlag = SEVERITY_SUCCESS; /* error flag to return */
|
||||
UINT32 flags; /* conversion flags seen */
|
||||
INT32 ncWidth; /* width for field */
|
||||
INT32 ncPrecision; /* precision for field */
|
||||
INT32 nBase; /* numeric base for field */
|
||||
INT64 input; /* input integer value */
|
||||
CHAR chConvert; /* conversion character for field */
|
||||
CHAR achBuffer[BUFSIZE]; /* buffer into which output is formatted */
|
||||
|
||||
while (*pszFormat)
|
||||
{
|
||||
/* locate all plain characters up to next % or end of string and output them */
|
||||
p = pszFormat;
|
||||
while (*p && (*p != '%'))
|
||||
p++;
|
||||
do_output(pszFormat, p - pszFormat);
|
||||
|
||||
if (*p == '%')
|
||||
{
|
||||
flags = 0; /* convert flags first */
|
||||
for (p++; (pFlag = StrChar8(szFlagChars, *p)) != NULL; p++)
|
||||
flags |= auiFlagValues[pFlag - szFlagChars];
|
||||
|
||||
ncWidth = 0; /* now convert width */
|
||||
if (*p == '*')
|
||||
{
|
||||
ncWidth = va_arg(pargs, INT32); /* specified by arg */
|
||||
p++;
|
||||
if (ncWidth < 0)
|
||||
{
|
||||
flags |= FLAG_LEFTJUST; /* negative width is taken as use of - flag */
|
||||
ncWidth = -ncWidth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (StrIsDigit8(*p))
|
||||
ncWidth = ncWidth * 10 + (*p++ - '0');
|
||||
}
|
||||
if (ncWidth > MAX_VAL)
|
||||
ncWidth = MAX_VAL;
|
||||
|
||||
ncPrecision = -1; /* now convert precision */
|
||||
if (*p == '.')
|
||||
{
|
||||
p++;
|
||||
if (*p == '*')
|
||||
{
|
||||
ncPrecision = va_arg(pargs, INT32); /* specified by arg */
|
||||
p++;
|
||||
/* N.B. ncPrecision < 0 = "omitted precision" */
|
||||
}
|
||||
else
|
||||
{
|
||||
ncPrecision = 0;
|
||||
while (StrIsDigit8(*p))
|
||||
ncPrecision = ncPrecision * 10 + (*p++ - '0');
|
||||
}
|
||||
if (ncPrecision > MAX_VAL)
|
||||
ncPrecision = MAX_VAL;
|
||||
}
|
||||
|
||||
chConvert = StrChar8(szConversionChars, *p) ? *p++ : '\0'; /* get conversion character */
|
||||
|
||||
/* based on field character, convert the field */
|
||||
pchOutput = achBuffer;
|
||||
nchOutput = 0;
|
||||
pchPrefix = NULL;
|
||||
nchPrefix = 0;
|
||||
nchZeroPrefix = 0;
|
||||
switch (*p)
|
||||
{
|
||||
case 'c': /* output a character */
|
||||
achBuffer[nchOutput++] = (CHAR)va_arg(pargs, INT32);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i': /* output a decimal number */
|
||||
if (ncPrecision < 0)
|
||||
ncPrecision = 1; /* default precision is 1 */
|
||||
if (chConvert == 'h')
|
||||
input = va_arg(pargs, INT32);
|
||||
else if (chConvert == '\0')
|
||||
input = va_arg(pargs, INT32);
|
||||
else
|
||||
input = va_arg(pargs, INT64);
|
||||
if ((input == 0) && (ncPrecision == 0))
|
||||
break; /* no output */
|
||||
|
||||
if (input < 0)
|
||||
{
|
||||
achBuffer[nchPrefix++] = '-'; /* minus sign */
|
||||
input = -input;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* plus or space for sign if flags dictate */
|
||||
if (flags & FLAG_PLUSSIGN)
|
||||
achBuffer[nchPrefix++] = '+';
|
||||
else if (flags & FLAG_SPACESIGN)
|
||||
achBuffer[nchPrefix++] = ' ';
|
||||
}
|
||||
if (nchPrefix > 0)
|
||||
{
|
||||
pchPrefix = achBuffer; /* adjust output pointer and set prefix */
|
||||
pchOutput = achBuffer + nchPrefix;
|
||||
}
|
||||
|
||||
/* clamp input value and run it through number conversion engine */
|
||||
if (chConvert == 'h')
|
||||
input &= UINT16_MAX;
|
||||
else if (chConvert == '\0')
|
||||
input &= UINT32_MAX;
|
||||
pFlag = pchOutput;
|
||||
pchOutput = convert_number_engine8((UINT64)input, pFlag, NUM_CONVERT_BYTES, 10, FALSE);
|
||||
nchOutput = (pFlag + NUM_CONVERT_BYTES) - pchOutput;
|
||||
|
||||
/* calculate zero prefix based on precision */
|
||||
if ((flags & (FLAG_ZEROPAD|FLAG_LEFTJUST)) == FLAG_ZEROPAD)
|
||||
nchZeroPrefix = intMax(0, ncWidth - (nchPrefix + nchOutput));
|
||||
else if (ncPrecision > 0)
|
||||
nchZeroPrefix = intMax(0, ncPrecision - nchOutput);
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'u':
|
||||
case 'x':
|
||||
case 'X': /* output an unsigned number */
|
||||
if (ncPrecision < 0)
|
||||
ncPrecision = 1; /* defualt precision is 1 */
|
||||
if (chConvert == 'h')
|
||||
input = va_arg(pargs, UINT32);
|
||||
else if (chConvert == '\0')
|
||||
input = va_arg(pargs, UINT32);
|
||||
else
|
||||
input = (INT64)va_arg(pargs, UINT64);
|
||||
if ((input == 0) && (ncPrecision == 0))
|
||||
break; /* no output */
|
||||
|
||||
/* select numeric base of output */
|
||||
if (*p == 'o')
|
||||
nBase = 8;
|
||||
else if (*p == 'u')
|
||||
nBase = 10;
|
||||
else
|
||||
nBase = 16;
|
||||
|
||||
if (flags & FLAG_ALTMODE)
|
||||
{
|
||||
if (*p == 'o')
|
||||
{ /* forced octal notation */
|
||||
achBuffer[nchPrefix++] = '0';
|
||||
ncPrecision--;
|
||||
}
|
||||
else if (*p != 'u')
|
||||
{ /* forced hexadecimal notation */
|
||||
achBuffer[nchPrefix++] = '0';
|
||||
achBuffer[nchPrefix++] = *p;
|
||||
}
|
||||
}
|
||||
if (nchPrefix > 0)
|
||||
{
|
||||
pchPrefix = achBuffer; /* adjust output pointer and set prefix */
|
||||
pchOutput = achBuffer + nchPrefix;
|
||||
}
|
||||
|
||||
/* clamp input value and run it through number conversion engine */
|
||||
if (chConvert == 'h')
|
||||
input &= UINT16_MAX;
|
||||
else if (chConvert == '\0')
|
||||
input &= UINT32_MAX;
|
||||
pFlag = pchOutput;
|
||||
pchOutput = convert_number_engine8((UINT64)input, pFlag, NUM_CONVERT_BYTES, nBase, MAKEBOOL(*p == 'X'));
|
||||
nchOutput = (pFlag + NUM_CONVERT_BYTES) - pchOutput;
|
||||
|
||||
/* calculate zero prefix based on precision */
|
||||
if ((flags & (FLAG_ZEROPAD|FLAG_LEFTJUST)) == FLAG_ZEROPAD)
|
||||
nchZeroPrefix = intMax(0, ncWidth - (nchPrefix + nchOutput));
|
||||
else if (ncPrecision > 0)
|
||||
nchZeroPrefix = intMax(0, ncPrecision - nchOutput);
|
||||
break;
|
||||
|
||||
case 'p': /* output a pointer value - treated as unsigned hex with precision of 8 */
|
||||
input = (INT_PTR)va_arg(pargs, PVOID);
|
||||
input &= UINT_PTR_MAX;
|
||||
pFlag = pchOutput;
|
||||
pchOutput = convert_number_engine8((UINT64)input, pFlag, NUM_CONVERT_BYTES, 16, FALSE);
|
||||
nchOutput = (pFlag + NUM_CONVERT_BYTES) - pchOutput;
|
||||
nchZeroPrefix = intMax(0, (sizeof(UINT_PTR) / sizeof(CHAR) * 2) - nchOutput);
|
||||
break;
|
||||
|
||||
case 's': /* output a string */
|
||||
pchOutput = (PCHAR)va_arg(pargs, PCSTR);
|
||||
nchOutput = StrLength8(pchOutput);
|
||||
if ((ncPrecision >= 0) && (ncPrecision < nchOutput))
|
||||
nchOutput = ncPrecision;
|
||||
break;
|
||||
|
||||
case 'n': /* output nothing, just store number of characters output so far */
|
||||
*(va_arg(pargs, PINT32)) = nTotalOutput;
|
||||
goto no_output;
|
||||
|
||||
case '%': /* output a single % sign */
|
||||
default: /* unrecognized format character, output it and continue */
|
||||
achBuffer[nchOutput++] = *p;
|
||||
break;
|
||||
}
|
||||
|
||||
ncWidth -= (nchPrefix + nchZeroPrefix + nchOutput);
|
||||
if (!(flags & FLAG_LEFTJUST))
|
||||
do_pad_output(szPadSpace, ncWidth);
|
||||
do_output(pchPrefix, nchPrefix);
|
||||
do_pad_output(szPadZero, nchZeroPrefix);
|
||||
do_output(pchOutput, nchOutput);
|
||||
if (flags & FLAG_LEFTJUST)
|
||||
do_pad_output(szPadSpace, ncWidth);
|
||||
|
||||
no_output:
|
||||
p++;
|
||||
}
|
||||
pszFormat = p;
|
||||
}
|
||||
error:
|
||||
return MAKE_SCODE(errorFlag, FACILITY_STRFORMAT, nTotalOutput);
|
||||
}
|
||||
185
kernel/lib/strcomparemem.S
Normal file
185
kernel/lib/strcomparemem.S
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2003 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Steve C. Woodford for Wasabi Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2002 ARM Ltd
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the company may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* Taken from FreeBSD memcmp.S, munged by Erbo to COMROGUE standards */
|
||||
/* Func: INT32 StrCompareMem(PCVOID pMem1, PCVOID pMem2, SSIZE_T cb); */
|
||||
/*
|
||||
* Compares two memory blocks as bytes, returning a value for comparison between the two.
|
||||
*
|
||||
* Parameters:
|
||||
* - pMem1 = First block of memory to compare.
|
||||
* - pMem2 = Second block of memory to compare.
|
||||
* - cb = Size of the two memory blocks in bytes.
|
||||
*
|
||||
* Returns:
|
||||
* 0 if the two memory blocks are the same; a value less than 0 if the memory block pointed to by pMem1 is
|
||||
* less than the one pointed to by pMem2; a value greater than 0 if the memory block pointed to by pMem1 is
|
||||
* greater than the one pointed to by pMem2.
|
||||
*/
|
||||
.globl StrCompareMem
|
||||
StrCompareMem:
|
||||
mov ip, r0
|
||||
cmp r2, #0x06 /* optimized version for 6-byte compares */
|
||||
beq .Lmemcmp_6bytes
|
||||
mov r0, #0x00
|
||||
|
||||
/* Are both addresses aligned the same way? */
|
||||
cmp r2, #0x00
|
||||
eornes r3, ip, r1
|
||||
bxeq lr /* len == 0, or same addresses! */
|
||||
tst r3, #0x03
|
||||
subne r2, r2, #0x01
|
||||
bne .Lmemcmp_bytewise2 /* Badly aligned. Do it the slow way */
|
||||
|
||||
/* Word-align the addresses, if necessary */
|
||||
sub r3, r1, #0x05
|
||||
ands r3, r3, #0x03
|
||||
add r3, r3, r3, lsl #1
|
||||
addne pc, pc, r3, lsl #3
|
||||
nop
|
||||
|
||||
/* Compare up to 3 bytes */
|
||||
ldrb r0, [ip], #0x01
|
||||
ldrb r3, [r1], #0x01
|
||||
subs r0, r0, r3
|
||||
bxne lr
|
||||
subs r2, r2, #0x01
|
||||
bxeq lr
|
||||
|
||||
/* Compare up to 2 bytes */
|
||||
ldrb r0, [ip], #0x01
|
||||
ldrb r3, [r1], #0x01
|
||||
subs r0, r0, r3
|
||||
bxne lr
|
||||
subs r2, r2, #0x01
|
||||
bxeq lr
|
||||
|
||||
/* Compare 1 byte */
|
||||
ldrb r0, [ip], #0x01
|
||||
ldrb r3, [r1], #0x01
|
||||
subs r0, r0, r3
|
||||
bxne lr
|
||||
subs r2, r2, #0x01
|
||||
bxeq lr
|
||||
|
||||
/* Compare 4 bytes at a time, if possible */
|
||||
subs r2, r2, #0x04
|
||||
bcc .Lmemcmp_bytewise
|
||||
.Lmemcmp_word_aligned:
|
||||
ldr r0, [ip], #0x04
|
||||
ldr r3, [r1], #0x04
|
||||
subs r2, r2, #0x04
|
||||
cmpcs r0, r3
|
||||
beq .Lmemcmp_word_aligned
|
||||
sub r0, r0, r3
|
||||
|
||||
/* Correct for extra subtraction, and check if done */
|
||||
adds r2, r2, #0x04
|
||||
cmpeq r0, #0x00 /* If done, did all bytes match? */
|
||||
bxeq lr /* Yup. Just return */
|
||||
|
||||
/* Re-do the final word byte-wise */
|
||||
sub ip, ip, #0x04
|
||||
sub r1, r1, #0x04
|
||||
|
||||
.Lmemcmp_bytewise:
|
||||
add r2, r2, #0x03
|
||||
.Lmemcmp_bytewise2:
|
||||
ldrb r0, [ip], #0x01
|
||||
ldrb r3, [r1], #0x01
|
||||
subs r2, r2, #0x01
|
||||
cmpcs r0, r3
|
||||
beq .Lmemcmp_bytewise2
|
||||
sub r0, r0, r3
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* 6 byte compares are very common, thanks to the network stack.
|
||||
* This code is hand-scheduled to reduce the number of stalls for
|
||||
* load results. Everything else being equal, this will be ~32%
|
||||
* faster than a byte-wise memcmp.
|
||||
*/
|
||||
.align 5
|
||||
.Lmemcmp_6bytes:
|
||||
ldrb r3, [r1, #0x00] /* r3 = b2#0 */
|
||||
ldrb r0, [ip, #0x00] /* r0 = b1#0 */
|
||||
ldrb r2, [r1, #0x01] /* r2 = b2#1 */
|
||||
subs r0, r0, r3 /* r0 = b1#0 - b2#0 */
|
||||
ldreqb r3, [ip, #0x01] /* r3 = b1#1 */
|
||||
bxne lr /* Return if mismatch on #0 */
|
||||
subs r0, r3, r2 /* r0 = b1#1 - b2#1 */
|
||||
ldreqb r3, [r1, #0x02] /* r3 = b2#2 */
|
||||
ldreqb r0, [ip, #0x02] /* r0 = b1#2 */
|
||||
bxne lr /* Return if mismatch on #1 */
|
||||
ldrb r2, [r1, #0x03] /* r2 = b2#3 */
|
||||
subs r0, r0, r3 /* r0 = b1#2 - b2#2 */
|
||||
ldreqb r3, [ip, #0x03] /* r3 = b1#3 */
|
||||
bxne lr /* Return if mismatch on #2 */
|
||||
subs r0, r3, r2 /* r0 = b1#3 - b2#3 */
|
||||
ldreqb r3, [r1, #0x04] /* r3 = b2#4 */
|
||||
ldreqb r0, [ip, #0x04] /* r0 = b1#4 */
|
||||
bxne lr /* Return if mismatch on #3 */
|
||||
ldrb r2, [r1, #0x05] /* r2 = b2#5 */
|
||||
subs r0, r0, r3 /* r0 = b1#4 - b2#4 */
|
||||
ldreqb r3, [ip, #0x05] /* r3 = b1#5 */
|
||||
bxne lr /* Return if mismatch on #4 */
|
||||
sub r0, r3, r2 /* r0 = b1#5 - b2#5 */
|
||||
bx lr
|
||||
271
kernel/lib/strcopymem.S
Normal file
271
kernel/lib/strcopymem.S
Normal file
@@ -0,0 +1,271 @@
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Neil A. Carson and Mark Brinicombe
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* Taken from FreeBSD memcpy_arm.S, munged by Erbo to COMROGUE standards */
|
||||
/*
|
||||
* This is one fun bit of code ...
|
||||
* Some easy listening music is suggested while trying to understand this
|
||||
* code e.g. Iron Maiden
|
||||
*
|
||||
* For anyone attempting to understand it :
|
||||
*
|
||||
* The core code is implemented here with simple stubs for memcpy().
|
||||
*
|
||||
* All local labels are prefixed with Lmemcpy_
|
||||
* Following the prefix a label starting f is used in the forward copy code
|
||||
* while a label using b is used in the backwards copy code
|
||||
* The source and destination addresses determine whether a forward or
|
||||
* backward copy is performed.
|
||||
* Separate bits of code are used to deal with the following situations
|
||||
* for both the forward and backwards copy.
|
||||
* unaligned source address
|
||||
* unaligned destination address
|
||||
* Separate copy routines are used to produce an optimised result for each
|
||||
* of these cases.
|
||||
* The copy code will use LDM/STM instructions to copy up to 32 bytes at
|
||||
* a time where possible.
|
||||
*
|
||||
* Note: r12 (aka ip) can be trashed during the function along with
|
||||
* r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
|
||||
* Additional registers are preserved prior to use i.e. r4, r5 & lr
|
||||
*
|
||||
* Apologies for the state of the comments ;-)
|
||||
*/
|
||||
/* Func: PVOID StrCopyMem(PVOID pDest, PCVOID pSrc, SSIZE_T cb); */
|
||||
/*
|
||||
* Copies memory data from one block of memory to another. Assumes the memory blocks do NOT overlap.
|
||||
*
|
||||
* Parameters:
|
||||
* - pDest = Destination for the copy operation.
|
||||
* - pSrc = Source for the copy operation.
|
||||
* - cb = Number of bytes to be copied.
|
||||
*
|
||||
* Returns:
|
||||
* pDest.
|
||||
*/
|
||||
.globl StrCopyMem
|
||||
StrCopyMem:
|
||||
/* save leaf functions having to store this away */
|
||||
stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
|
||||
|
||||
subs r2, r2, #4
|
||||
blt .Lmemcpy_l4 /* less than 4 bytes */
|
||||
ands r12, r0, #3
|
||||
bne .Lmemcpy_destul /* oh unaligned destination addr */
|
||||
ands r12, r1, #3
|
||||
bne .Lmemcpy_srcul /* oh unaligned source addr */
|
||||
|
||||
.Lmemcpy_t8:
|
||||
/* We have aligned source and destination */
|
||||
subs r2, r2, #8
|
||||
blt .Lmemcpy_l12 /* less than 12 bytes (4 from above) */
|
||||
subs r2, r2, #0x14
|
||||
blt .Lmemcpy_l32 /* less than 32 bytes (12 from above) */
|
||||
stmdb sp!, {r4} /* borrow r4 */
|
||||
|
||||
/* blat 32 bytes at a time */
|
||||
/* XXX for really big copies perhaps we should use more registers */
|
||||
.Lmemcpy_loop32:
|
||||
ldmia r1!, {r3, r4, r12, lr}
|
||||
stmia r0!, {r3, r4, r12, lr}
|
||||
ldmia r1!, {r3, r4, r12, lr}
|
||||
stmia r0!, {r3, r4, r12, lr}
|
||||
subs r2, r2, #0x20
|
||||
bge .Lmemcpy_loop32
|
||||
|
||||
cmn r2, #0x10
|
||||
ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
|
||||
stmgeia r0!, {r3, r4, r12, lr}
|
||||
subge r2, r2, #0x10
|
||||
ldmia sp!, {r4} /* return r4 */
|
||||
|
||||
.Lmemcpy_l32:
|
||||
adds r2, r2, #0x14
|
||||
|
||||
/* blat 12 bytes at a time */
|
||||
.Lmemcpy_loop12:
|
||||
ldmgeia r1!, {r3, r12, lr}
|
||||
stmgeia r0!, {r3, r12, lr}
|
||||
subges r2, r2, #0x0c
|
||||
bge .Lmemcpy_loop12
|
||||
|
||||
.Lmemcpy_l12:
|
||||
adds r2, r2, #8
|
||||
blt .Lmemcpy_l4
|
||||
|
||||
subs r2, r2, #4
|
||||
ldrlt r3, [r1], #4
|
||||
strlt r3, [r0], #4
|
||||
ldmgeia r1!, {r3, r12}
|
||||
stmgeia r0!, {r3, r12}
|
||||
subge r2, r2, #4
|
||||
|
||||
.Lmemcpy_l4:
|
||||
/* less than 4 bytes to go */
|
||||
adds r2, r2, #4
|
||||
ldmeqia sp!, {r0, pc} /* done */
|
||||
|
||||
/* copy the crud byte at a time */
|
||||
cmp r2, #2
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
ldrgeb r3, [r1], #1
|
||||
strgeb r3, [r0], #1
|
||||
ldrgtb r3, [r1], #1
|
||||
strgtb r3, [r0], #1
|
||||
ldmia sp!, {r0, pc}
|
||||
|
||||
/* erg - unaligned destination */
|
||||
.Lmemcpy_destul:
|
||||
rsb r12, r12, #4
|
||||
cmp r12, #2
|
||||
|
||||
/* align destination with byte copies */
|
||||
ldrb r3, [r1], #1
|
||||
strb r3, [r0], #1
|
||||
ldrgeb r3, [r1], #1
|
||||
strgeb r3, [r0], #1
|
||||
ldrgtb r3, [r1], #1
|
||||
strgtb r3, [r0], #1
|
||||
subs r2, r2, r12
|
||||
blt .Lmemcpy_l4 /* less the 4 bytes */
|
||||
|
||||
ands r12, r1, #3
|
||||
beq .Lmemcpy_t8 /* we have an aligned source */
|
||||
|
||||
/* erg - unaligned source */
|
||||
/* This is where it gets nasty ... */
|
||||
.Lmemcpy_srcul:
|
||||
bic r1, r1, #3
|
||||
ldr lr, [r1], #4
|
||||
cmp r12, #2
|
||||
bgt .Lmemcpy_srcul3
|
||||
beq .Lmemcpy_srcul2
|
||||
cmp r2, #0x0c
|
||||
blt .Lmemcpy_srcul1loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5}
|
||||
|
||||
.Lmemcpy_srcul1loop16:
|
||||
mov r3, lr, lsr #8
|
||||
ldmia r1!, {r4, r5, r12, lr}
|
||||
orr r3, r3, r4, lsl #24
|
||||
mov r4, r4, lsr #8
|
||||
orr r4, r4, r5, lsl #24
|
||||
mov r5, r5, lsr #8
|
||||
orr r5, r5, r12, lsl #24
|
||||
mov r12, r12, lsr #8
|
||||
orr r12, r12, lr, lsl #24
|
||||
stmia r0!, {r3-r5, r12}
|
||||
subs r2, r2, #0x10
|
||||
bge .Lmemcpy_srcul1loop16
|
||||
ldmia sp!, {r4, r5}
|
||||
adds r2, r2, #0x0c
|
||||
blt .Lmemcpy_srcul1l4
|
||||
|
||||
.Lmemcpy_srcul1loop4:
|
||||
mov r12, lr, lsr #8
|
||||
ldr lr, [r1], #4
|
||||
orr r12, r12, lr, lsl #24
|
||||
str r12, [r0], #4
|
||||
subs r2, r2, #4
|
||||
bge .Lmemcpy_srcul1loop4
|
||||
|
||||
.Lmemcpy_srcul1l4:
|
||||
sub r1, r1, #3
|
||||
b .Lmemcpy_l4
|
||||
|
||||
.Lmemcpy_srcul2:
|
||||
cmp r2, #0x0c
|
||||
blt .Lmemcpy_srcul2loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5}
|
||||
|
||||
.Lmemcpy_srcul2loop16:
|
||||
mov r3, lr, lsr #16
|
||||
ldmia r1!, {r4, r5, r12, lr}
|
||||
orr r3, r3, r4, lsl #16
|
||||
mov r4, r4, lsr #16
|
||||
orr r4, r4, r5, lsl #16
|
||||
mov r5, r5, lsr #16
|
||||
orr r5, r5, r12, lsl #16
|
||||
mov r12, r12, lsr #16
|
||||
orr r12, r12, lr, lsl #16
|
||||
stmia r0!, {r3-r5, r12}
|
||||
subs r2, r2, #0x10
|
||||
bge .Lmemcpy_srcul2loop16
|
||||
ldmia sp!, {r4, r5}
|
||||
adds r2, r2, #0x0c
|
||||
blt .Lmemcpy_srcul2l4
|
||||
|
||||
.Lmemcpy_srcul2loop4:
|
||||
mov r12, lr, lsr #16
|
||||
ldr lr, [r1], #4
|
||||
orr r12, r12, lr, lsl #16
|
||||
str r12, [r0], #4
|
||||
subs r2, r2, #4
|
||||
bge .Lmemcpy_srcul2loop4
|
||||
|
||||
.Lmemcpy_srcul2l4:
|
||||
sub r1, r1, #2
|
||||
b .Lmemcpy_l4
|
||||
|
||||
.Lmemcpy_srcul3:
|
||||
cmp r2, #0x0c
|
||||
blt .Lmemcpy_srcul3loop4
|
||||
sub r2, r2, #0x0c
|
||||
stmdb sp!, {r4, r5}
|
||||
|
||||
.Lmemcpy_srcul3loop16:
|
||||
mov r3, lr, lsr #24
|
||||
ldmia r1!, {r4, r5, r12, lr}
|
||||
orr r3, r3, r4, lsl #8
|
||||
mov r4, r4, lsr #24
|
||||
orr r4, r4, r5, lsl #8
|
||||
mov r5, r5, lsr #24
|
||||
orr r5, r5, r12, lsl #8
|
||||
mov r12, r12, lsr #24
|
||||
orr r12, r12, lr, lsl #8
|
||||
stmia r0!, {r3-r5, r12}
|
||||
subs r2, r2, #0x10
|
||||
bge .Lmemcpy_srcul3loop16
|
||||
ldmia sp!, {r4, r5}
|
||||
adds r2, r2, #0x0c
|
||||
blt .Lmemcpy_srcul3l4
|
||||
|
||||
.Lmemcpy_srcul3loop4:
|
||||
mov r12, lr, lsr #24
|
||||
ldr lr, [r1], #4
|
||||
orr r12, r12, lr, lsl #8
|
||||
str r12, [r0], #4
|
||||
subs r2, r2, #4
|
||||
bge .Lmemcpy_srcul3loop4
|
||||
|
||||
.Lmemcpy_srcul3l4:
|
||||
sub r1, r1, #1
|
||||
b .Lmemcpy_l4
|
||||
181
kernel/lib/strsetmem.S
Normal file
181
kernel/lib/strsetmem.S
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2003 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Steve C. Woodford for Wasabi Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1995 Mark Brinicombe.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by Mark Brinicombe.
|
||||
* 4. The name of the company nor the name of the author may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/* Taken from FreeBSD memset.S, munged by Erbo to COMROGUE standards */
|
||||
/* FUNC: PVOID StrSetMem(PVOID pMem, INT32 ch, SSIZE_T cb); */
|
||||
/*
|
||||
* Fills a block of memory with a constant byte value.
|
||||
*
|
||||
* Parameters:
|
||||
* - pMem = Pointer to the memory block to be filled.
|
||||
* - ch = The constant byte (character) to fill that memory with.
|
||||
* - cb = The size in bytes of the memory block to be filled.
|
||||
*
|
||||
* Returns:
|
||||
* pMem.
|
||||
*/
|
||||
.globl StrSetMem
|
||||
StrSetMem:
|
||||
and r3, r1, #0xff /* We deal with bytes */
|
||||
mov r1, r2
|
||||
cmp r1, #0x04 /* Do we have less than 4 bytes */
|
||||
mov ip, r0
|
||||
blt .Lmemset_lessthanfour
|
||||
|
||||
/* Ok first we will word align the address */
|
||||
ands r2, ip, #0x03 /* Get the bottom two bits */
|
||||
bne .Lmemset_wordunaligned /* The address is not word aligned */
|
||||
|
||||
/* We are now word aligned */
|
||||
.Lmemset_wordaligned:
|
||||
orr r3, r3, r3, lsl #8 /* Extend value to 16-bits */
|
||||
tst ip, #0x04 /* Quad-align for armv5e */
|
||||
orr r3, r3, r3, lsl #16 /* Extend value to 32-bits */
|
||||
subne r1, r1, #0x04 /* Quad-align if necessary */
|
||||
strne r3, [ip], #0x04
|
||||
cmp r1, #0x10
|
||||
blt .Lmemset_loop4 /* If less than 16 then use words */
|
||||
mov r2, r3 /* Duplicate data */
|
||||
cmp r1, #0x80 /* If < 128 then skip the big loop */
|
||||
blt .Lmemset_loop32
|
||||
|
||||
/* Do 128 bytes at a time */
|
||||
.Lmemset_loop128:
|
||||
subs r1, r1, #0x80
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
bgt .Lmemset_loop128
|
||||
bxeq lr /* Zero length so just exit */
|
||||
|
||||
add r1, r1, #0x80 /* Adjust for extra sub */
|
||||
|
||||
/* Do 32 bytes at a time */
|
||||
.Lmemset_loop32:
|
||||
subs r1, r1, #0x20
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
bgt .Lmemset_loop32
|
||||
bxeq lr /* Zero length so just exit */
|
||||
|
||||
adds r1, r1, #0x10 /* Partially adjust for extra sub */
|
||||
|
||||
/* Deal with 16 bytes or more */
|
||||
strged r2, [ip], #0x08
|
||||
strged r2, [ip], #0x08
|
||||
bxeq lr /* Zero length so just exit */
|
||||
|
||||
addlt r1, r1, #0x10 /* Possibly adjust for extra sub */
|
||||
|
||||
/* We have at least 4 bytes so copy as words */
|
||||
.Lmemset_loop4:
|
||||
subs r1, r1, #0x04
|
||||
strge r3, [ip], #0x04
|
||||
bgt .Lmemset_loop4
|
||||
bxeq lr /* Zero length so just exit */
|
||||
|
||||
/* Compensate for 64-bit alignment check */
|
||||
adds r1, r1, #0x04
|
||||
bxeq lr
|
||||
cmp r1, #2
|
||||
|
||||
strb r3, [ip], #0x01 /* Set 1 byte */
|
||||
strgeb r3, [ip], #0x01 /* Set another byte */
|
||||
strgtb r3, [ip] /* and a third */
|
||||
bx lr /* Exit */
|
||||
|
||||
.Lmemset_wordunaligned:
|
||||
rsb r2, r2, #0x004
|
||||
strb r3, [ip], #0x01 /* Set 1 byte */
|
||||
cmp r2, #0x02
|
||||
strgeb r3, [ip], #0x01 /* Set another byte */
|
||||
sub r1, r1, r2
|
||||
strgtb r3, [ip], #0x01 /* and a third */
|
||||
cmp r1, #0x04 /* More than 4 bytes left? */
|
||||
bge .Lmemset_wordaligned /* Yup */
|
||||
|
||||
.Lmemset_lessthanfour:
|
||||
cmp r1, #0x00
|
||||
bxeq lr /* Zero length so exit */
|
||||
strb r3, [ip], #0x01 /* Set 1 byte */
|
||||
cmp r1, #0x02
|
||||
strgeb r3, [ip], #0x01 /* Set another byte */
|
||||
strgtb r3, [ip] /* and a third */
|
||||
bx lr /* Exit */
|
||||
Reference in New Issue
Block a user