/* * R4000 double-word version. Only works in kernel mode. * Requires low-core support to save R5 and R6 in a 64-bit hole. */ /* * R4000 instructions */ #define LD(offset, base, rt) WORD $((067<<26)|((base)<<21)|((rt)<<16)|((offset)&0xFFFF)) #define STD(rt, offset, base) WORD $((077<<26)|((base)<<21)|((rt)<<16)|((offset)&0xFFFF)) TEXT memmove(SB), $0 JMP move TEXT memcpy(SB), $0 move: MOVW R1, s1+0(FP) MOVW n+8(FP), R3 /* R3 is count */ MOVW R1, R4 /* R4 is to-pointer */ SGT R0, R3, R10 BEQ R10, ok MOVW (R0), R0 /* abort if negative count */ ok: MOVW s2+4(FP), R10 /* R10 is from-pointer */ ADDU R3,R10, R7 /* R7 is end from-pointer */ ADDU R3,R4, R11 /* R11 is end to-pointer */ /* * easiest test is copy backwards if * destination string has higher mem address */ SGT $8,R3, R2 SGTU R4,R10, R1 BNE R1, back /* * if not at least 8 chars, * dont even mess around. * 7 chars to guarantee any * rounding up to a doubleword * boundary and 8 characters * to get at least maybe one * full doubleword store. */ BNE R2, fout /* * test if both pointers * are similarly word aligned */ XOR R4,R10, R1 AND $3, R1 BNE R1, fout /* * test if both pointers * are similarly double-word aligned */ XOR R4,R10, R1 AND $7, R1 BNE R1, f1 /* * double-word aligned; start by byte at a time until aligned */ fd1: AND $7,R4, R1 BEQ R1, fd2 MOVB 0(R10), R8 ADDU $1, R10 MOVB R8, 0(R4) ADDU $1, R4 JMP fd1 /* * turn R3 into to-end pointer-31 * copy 32 at a time while there's room. * R11 is smaller than R7 -- * there are problems if R7 is 0. */ fd2: ADDU $-31,R11, R3 fd3: SGTU R3,R4, R1 BEQ R1, f4 LD (0,(10), 5) /* MOVW 0(R10), R8 */ LD (8,(10), 6) /* MOVW 4(R10), R9 */ STD (5, 0,(4)) /* MOVW R8, 0(R4) */ LD (16,(10), 5) /* MOVW 8(R10), R8 */ STD (6, 8,(4)) /* MOVW R9, 4(R4) */ LD (24,(10), 6) /* MOVW 12(R10), R9 */ ADDU $32, R10 STD (5, 16,(4)) /* MOVW R8, 8(R4) */ STD (6, 24,(4)) /* MOVW R9, 12(R4) */ ADDU $32, R4 JMP fd3 /* * byte at a time to word align */ f1: AND $3,R4, R1 BEQ R1, f2 MOVB 0(R10), R8 ADDU $1, R10 MOVB R8, 0(R4) ADDU $1, R4 JMP f1 /* * turn R3 into to-end pointer-15 * copy 16 at a time while there's room. * R11 is smaller than R7 -- * there are problems if R7 is 0. */ f2: ADDU $-15,R11, R3 f3: SGTU R3,R4, R1 BEQ R1, f4 MOVW 0(R10), R8 MOVW 4(R10), R9 MOVW R8, 0(R4) MOVW 8(R10), R8 MOVW R9, 4(R4) MOVW 12(R10), R9 ADDU $16, R10 MOVW R8, 8(R4) MOVW R9, 12(R4) ADDU $16, R4 JMP f3 /* * turn R3 into to-end pointer-3 * copy 4 at a time while theres room */ f4: ADDU $-3,R11, R3 f5: SGTU R3,R4, R1 BEQ R1, fout MOVW 0(R10), R8 ADDU $4, R10 MOVW R8, 0(R4) ADDU $4, R4 JMP f5 /* * last loop, copy byte at a time */ fout: BEQ R7,R10, ret MOVB 0(R10), R8 ADDU $1, R10 MOVB R8, 0(R4) ADDU $1, R4 JMP fout /* * whole thing repeated for backwards */ back: BNE R2, bout XOR R11,R7, R1 AND $3, R1 BNE R1, bout XOR R11,R7, R1 AND $7, R1 BNE R1, b1 /* double words */ bd1: AND $7,R7, R1 BEQ R1, bd2 MOVB -1(R7), R8 ADDU $-1, R7 MOVB R8, -1(R11) ADDU $-1, R11 JMP bd1 bd2: ADDU $31,R10, R3 bd3: SGTU R7,R3, R1 BEQ R1, b4 LD (-8,(7), 5) /* MOVW -4(R7), R8 */ LD (-16,(7), 6) /* MOVW -8(R7), R9 */ STD (5, -8,(11)) /* MOVW R8, -4(R11) */ LD (-24,(7), 5) /* MOVW -12(R7), R8 */ STD (6, -16,(11)) /* MOVW R9, -8(R11) */ LD (-32,(7), 6) /* MOVW -16(R7), R9 */ ADDU $-32, R7 STD (5, -24,(11)) /* MOVW R8, -12(R11) */ STD (6, -32,(11)) /* MOVW R9, -16(R11) */ ADDU $-32, R11 JMP bd3 /* regular words */ b1: AND $3,R7, R1 BEQ R1, b2 MOVB -1(R7), R8 ADDU $-1, R7 MOVB R8, -1(R11) ADDU $-1, R11 JMP b1 b2: ADDU $15,R10, R3 b3: SGTU R7,R3, R1 BEQ R1, b4 MOVW -4(R7), R8 MOVW -8(R7), R9 MOVW R8, -4(R11) MOVW -12(R7), R8 MOVW R9, -8(R11) MOVW -16(R7), R9 ADDU $-16, R7 MOVW R8, -12(R11) MOVW R9, -16(R11) ADDU $-16, R11 JMP b3 b4: ADDU $3,R10, R3 b5: SGTU R7,R3, R1 BEQ R1, bout MOVW -4(R7), R8 ADDU $-4, R7 MOVW R8, -4(R11) ADDU $-4, R11 JMP b5 bout: BEQ R7,R10, ret MOVB -1(R7), R8 ADDU $-1, R7 MOVB R8, -1(R11) ADDU $-1, R11 JMP bout ret: MOVW s1+0(FP), R1 RET END