| /* |
| * 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 |