mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-28 05:51:04 +00:00
186 lines
2.8 KiB
ArmAsm
186 lines
2.8 KiB
ArmAsm
/*
|
|
* memcmp routine for Z8000
|
|
* Copyright (C) 2004 Christian Groessler <chris@groessler.org>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this file
|
|
* for any purpose is hereby granted without fee, provided that
|
|
* the above copyright notice and this notice appears in all
|
|
* copies.
|
|
*
|
|
* This file is distributed WITHOUT ANY WARRANTY; without even the implied
|
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
*/
|
|
|
|
/* int memcmp(const void *b1, const void *b2, size_t length);
|
|
*/
|
|
|
|
name "memcmp.S"
|
|
|
|
.text
|
|
even
|
|
global _memcmp
|
|
|
|
_memcmp:
|
|
|
|
#ifdef __Z8001__
|
|
segm
|
|
|
|
#ifdef __STD_CALL__
|
|
ldl rr6,rr14(#4)
|
|
ldl rr4,rr14(#8)
|
|
ldl rr2,rr14(#12)
|
|
#endif
|
|
|
|
/* rr2 - length (high word ignored)
|
|
* rr4 - b2
|
|
* rr6 - b1
|
|
*/
|
|
|
|
clr r1 /* initialize return value */
|
|
testl rr2
|
|
jr z,finish
|
|
|
|
bitb rl7,#0 /* odd b1? */
|
|
jr nz,testb2
|
|
bitb rl5,#0 /* odd b2? */
|
|
jr nz,odd_cmp /* b1 even, b2 odd */
|
|
jr t,even_cmp
|
|
|
|
testb2:
|
|
bitb rl5,#0
|
|
jr z,odd_cmp /* b2 even, b1 odd */
|
|
|
|
cpsib @rr6,@rr4,r3,eq
|
|
jr z,beq /* bytes are the same */
|
|
jr t,byte_diff
|
|
|
|
beq: jr ov,finish /* jump if r3 is zero now */
|
|
|
|
/* compare words */
|
|
even_cmp:
|
|
ld r2,r3 /* remember length */
|
|
srl r3,#1
|
|
jr z,no_words
|
|
|
|
cpsir @rr6,@rr4,r3,ne
|
|
jr nz,no_words
|
|
|
|
dec r7,#2
|
|
dec r5,#2 /* point to different bytes */
|
|
ldk r3,#2
|
|
jr t,odd_cmp
|
|
|
|
no_words:
|
|
bitb rl2,#0 /* odd length? */
|
|
jr z,finish
|
|
|
|
cpsib @rr6,@rr4,r3,eq
|
|
jr z,finish /* last bytes are the same */
|
|
jr t,byte_diff
|
|
|
|
/* compare bytes */
|
|
odd_cmp:
|
|
cpsirb @rr6,@rr4,r3,ne
|
|
jr nz,finish
|
|
|
|
byte_diff:
|
|
dec r7,#1
|
|
dec r5,#1 /* point to different bytes */
|
|
|
|
ldb rl1,@rr6
|
|
clr r0
|
|
ldb rl0,@rr4
|
|
sub r1,r0
|
|
|
|
finish: /* set return value */
|
|
#ifdef __STD_CALL__
|
|
ld r7,r1
|
|
#else
|
|
ld r2,r1
|
|
#endif
|
|
|
|
|
|
#else /* above Z8001, below Z8002 */
|
|
|
|
|
|
unsegm
|
|
|
|
#ifdef __STD_CALL__
|
|
ld r7,r15(#2)
|
|
ld r6,r15(#4)
|
|
ld r5,r15(#6)
|
|
#endif
|
|
|
|
/* r5 - length
|
|
* r6 - b2
|
|
* r7 - b1
|
|
*/
|
|
|
|
clr r1 /* initialize return value */
|
|
test r5
|
|
jr z,finish
|
|
|
|
bitb rl7,#0 /* odd destination address? */
|
|
jr nz,testb2
|
|
bitb rl6,#0 /* odd source address? */
|
|
jr nz,odd_cmp /* b1 even, b2 odd */
|
|
jr t,even_cmp
|
|
|
|
testb2:
|
|
bitb rl6,#0
|
|
jr z,odd_cmp /* b2 even, b1 odd */
|
|
|
|
cpsib @r7,@r6,r5,eq
|
|
jr z,beq /* bytes are the same */
|
|
jr t,byte_diff
|
|
|
|
beq: jr ov,finish /* jump if r3 is zero now */
|
|
|
|
/* compare words */
|
|
even_cmp:
|
|
ld r4,r5 /* remember length */
|
|
srl r5,#1
|
|
jr z,no_words
|
|
|
|
cpsir @r7,@r6,r5,ne
|
|
jr nz,no_words
|
|
|
|
dec r7,#2
|
|
dec r6,#2 /* point to different bytes */
|
|
ldk r5,#2
|
|
jr t,odd_cmp
|
|
|
|
no_words:
|
|
bitb rl4,#0 /* odd length? */
|
|
jr z,finish
|
|
|
|
cpsib @r7,@r6,r4,eq
|
|
jr z,finish /* last bytes are the same */
|
|
jr t,byte_diff
|
|
|
|
/* compare bytes */
|
|
odd_cmp:
|
|
cpsirb @r7,@r6,r5,ne
|
|
jr nz,finish
|
|
|
|
byte_diff:
|
|
dec r7,#1
|
|
dec r6,#1 /* point to different bytes */
|
|
|
|
ldb rl1,@r7
|
|
clr r0
|
|
ldb rl0,@r6
|
|
sub r1,r0
|
|
|
|
finish:
|
|
#ifdef __STD_CALL__
|
|
ld r7,r1
|
|
#else
|
|
ld r2,r1
|
|
#endif
|
|
|
|
#endif /* Z8002 */
|
|
|
|
ret
|
|
.end
|