📄 balib.s
字号:
ldrb tmp3, [src, #-1]! /* 1st byte */ strb tmp3, [dst, #-1]! ldrb tmp3, [src, #-1]! /* 2nd byte */ strb tmp3, [dst, #-1]!#ifdef STACK_FRAMES ldmdb fp, {v1, fp, sp, pc}#else /* !STACK_FRAMES */ ldmfd sp!, {v1, pc} /* Done */#endif /* STACK_FRAMES *//* * forward copy: * The copy loop is rolled out in one loop of 16 word copies. The loop is * initiated by jumping into the loop at location (n % 16). */copyWords_Forward: /* Check if 16-bit aligned */ tst src, #2 /* 16 bit aligned */ beq ForwW_Aligned ldrb tmp3, [src], #1 /* Extra word, 1st byte*/ strb tmp3, [dst], #1 ldrb tmp3, [src], #1 /* Extra word, 2nd byte*/ strb tmp3, [dst], #1 subs n, n, #1 /* One less */#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc} /* Done ? */#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Done ? */#endif /* STACK_FRAMES */ForwW_Aligned: /* Copy 16 longs (32 shorts) ? */ subs n, n, #32 blt CWF_LT32ForwW_Loop: /* Loop here while we have > 32 words to copy */ ldmia src!, {tmp1, v1, tmp3, lr} /* 8 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmia src!, {tmp1, v1, tmp3, lr} /* 16 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmia src!, {tmp1, v1, tmp3, lr} /* 24 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmia src!, {tmp1, v1, tmp3, lr} /* 32 */ stmia dst!, {tmp1, v1, tmp3, lr} subs n, n, #32 bge ForwW_LoopCWF_LT32: /* Here is less than 32 longs to copy */ adds n, n, #32#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc} /* Done */#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Done */#endif /* STACK_FRAMES */ /* Possible 24 to copy */ movs tmp1, n, asr #3 /* How many groups of 8 ? */ beq CWF_LT8 /* None */ /* Remove 8/16/24 from the counter */ sub n, n, tmp1, asl #3 /* 8, 16 or 24 words */ cmp tmp1, #2 ldmia src!, {tmp1, v1, tmp3, lr} /* 8 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmgeia src!, {tmp1, v1, tmp3, lr} /* 18 */ stmgeia dst!, {tmp1, v1, tmp3, lr} ldmgtia src!, {tmp1, v1, tmp3, lr} /* 24 */ stmgtia dst!, {tmp1, v1, tmp3, lr} /* Less than 8 words to copy */ cmp n, #0 /* Anything left ? */#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc}#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Nope, done */#endif /* STACK_FRAMES */ /* Convert to complete 32-bit words (0,1,2,3) */CWF_LT8: movs tmp1, n, asr #1 /* 32-bit words */ beq CWF_EQ1 /* 0*32-bit, 1*16 words left? */ cmp tmp1, #2 ldr tmp3, [src], #4 /* 1 */ str tmp3, [dst], #4 ldrge tmp3, [src], #4 /* 2 */ strge tmp3, [dst], #4 ldrgt tmp3, [src], #4 /* 3 */ strgt tmp3, [dst], #4 subs n, n, tmp1, asl #1 /* Take off amount we copied */#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc} /* Done ? */#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Done ? */#endif /* STACK_FRAMES */CWF_EQ1: ldrb tmp3, [src], #1 /* 1st byte */ strb tmp3, [dst], #1 ldrb tmp3, [src], #1 /* 2nd byte */ strb tmp3, [dst], #1#ifdef STACK_FRAMES ldmdb fp, {v1, fp, sp, pc}#else /* !STACK_FRAMES */ ldmfd sp!, {v1, pc} /* Done */#endif /* STACK_FRAMES */#endif /* ARM_HAS_HALFWORD_INSTRUCTIONS *//* bcopyWords End *//********************************************************************************* bcopyLongs - copy one buffer to another one long at a time** This routine copies the first <nlongs> longs from <source> to <destination>* one long at a time. This may be desirable if a buffer can only be accessed* with long instructions, as in certain long-wide memory-mapped peripherals.* The source and destination must be long-aligned.** RETURNS: N/A** NOMANUAL** void bcopyLongs* (* char * source, /@ pointer to source buffer @/* char * destination, /@ pointer to destination buffer @/* int longs /@ number of longs to copy @/* )*/FUNC_LABEL(bcopyLongs)#ifdef STACK_FRAMES mov ip, sp stmdb sp!, {v1, fp, ip, lr, pc} sub fp, ip, #4#endif /* STACK_FRAMES */ /* Quick check for 0 */ cmp n, #0#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc}#else /* !STACK_FRAMES */ moveq pc, lr#endif /* STACK_FRAMES */ /* Determine if forward or backward copy required */ subs tmp1, dst, src#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc}#else /* !STACK_FRAMES */ moveq pc, lr /* Same */#endif /* STACK_FRAMES */#ifndef STACK_FRAMES stmfd sp!, {v1, lr} /* Save regs */#endif /* STACK_FRAMES */ blt copyLongs_Forward mov tmp3, n, asl #2 /* Convert to bytes */ cmp tmp1, tmp3 bge copyLongs_Forward/* * backward copy * The copy loop is rolled out in one loop of 16 long copies and * one of 4 long copies. The remainder is done on a simple conditional. */ /* Adjust pointers to the end of the buffer */ add dst, dst, tmp3 add src, src, tmp3 /* Copy 16 Longs ? */ subs n, n, #16 blt CLB_LT16CLB_16: /* Loop here while we have > 16 longs to copy */ ldmdb src!, {tmp1, v1, tmp3, lr} /* 4 */ stmdb dst!, {tmp1, v1, tmp3, lr} ldmdb src!, {tmp1, v1, tmp3, lr} /* 8 */ stmdb dst!, {tmp1, v1, tmp3, lr} ldmdb src!, {tmp1, v1, tmp3, lr} /* 12 */ stmdb dst!, {tmp1, v1, tmp3, lr} ldmdb src!, {tmp1, v1, tmp3, lr} /* 16 */ stmdb dst!, {tmp1, v1, tmp3, lr} subs n, n, #16 bge CLB_16CLB_LT16: /* Here if less than 16 longs to copy */ adds n, n, #16#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc} /* Done */#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Done */#endif /* STACK_FRAMES */ /* Possible 12 to copy */ movs tmp1, n, asr #2 /* How many groups of 4 ? */ beq CLB_LT4 /* None ! */ /* Remove 4/8/12 from the counter */ sub n, n, tmp1, asl #2 /* 4, 8 or 12 longs */ cmp tmp1, #2 ldmdb src!, {tmp1, v1, tmp3, lr} /* 4 */ stmdb dst!, {tmp1, v1, tmp3, lr} ldmgedb src!, {tmp1, v1, tmp3, lr} /* 8 */ stmgedb dst!, {tmp1, v1, tmp3, lr} ldmgtdb src!, {tmp1, v1, tmp3, lr} /* 12 */ stmgtdb dst!, {tmp1, v1, tmp3, lr} /* Less than 4 longs to copy */ cmp n, #0 /* Anything left ? */#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc} /* Nope, done */#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Nope, done */#endif /* STACK_FRAMES */CLB_LT4: /* 1, 2 or 3 */ cmp n, #2 ldr tmp3, [src, #-4]! /* 1 */ str tmp3, [dst, #-4]! ldrge tmp3, [src, #-4]! /* 2 */ strge tmp3, [dst, #-4]! ldrgt tmp3, [src, #-4]! /* 3 */ strgt tmp3, [dst, #-4]! /* Return */#ifdef STACK_FRAMES ldmdb fp, {v1, fp, sp, pc}#else /* !STACK_FRAMES */ ldmfd sp!, {v1, pc}#endif /* STACK_FRAMES *//* * forward copy * The copy loop is rolled out in one loop of 16 long copies and * one of 4 long copies. The remainder is done on a simple conditional. */copyLongs_Forward: /* Copy 16 Longs ? */ subs n, n, #16 blt CLF_LT16CLF_16: /* Loop here while we have > 16 longs to copy */ ldmia src!, {tmp1, v1, tmp3, lr} /* 4 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmia src!, {tmp1, v1, tmp3, lr} /* 8 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmia src!, {tmp1, v1, tmp3, lr} /* 12 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmia src!, {tmp1, v1, tmp3, lr} /* 16 */ stmia dst!, {tmp1, v1, tmp3, lr} subs n, n, #16 bge CLF_16CLF_LT16: /* Here if less than 16 longs to copy */ adds n, n, #16#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc} /* Done */#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Done */#endif /* STACK_FRAMES */ /* Possible 12 to copy */ movs tmp1, n, asr #2 /* How many groups of 4 ? */ beq CLF_LT4 /* None ! */ /* Remove 4/8/12 from the counter */ sub n, n, tmp1, asl #2 /* 4, 8 or 12 longs */ cmp tmp1, #2 ldmia src!, {tmp1, v1, tmp3, lr} /* 4 */ stmia dst!, {tmp1, v1, tmp3, lr} ldmgeia src!, {tmp1, v1, tmp3, lr} /* 8 */ stmgeia dst!, {tmp1, v1, tmp3, lr} ldmgtia src!, {tmp1, v1, tmp3, lr} /* 12 */ stmgtia dst!, {tmp1, v1, tmp3, lr} /* Less than 4 longs to copy */ cmp n, #0 /* Anything left ? */#ifdef STACK_FRAMES ldmeqdb fp, {v1, fp, sp, pc} /* Nope, done */#else /* !STACK_FRAMES */ ldmeqfd sp!, {v1, pc} /* Nope, done */#endif /* STACK_FRAMES */CLF_LT4: /* 1, 2 or 3 */ cmp n, #2 ldr tmp3, [src], #4 /* 1 */ str tmp3, [dst], #4 ldrge tmp3, [src], #4 /* 2 */ strge tmp3, [dst], #4 ldrgt tmp3, [src], #4 /* 3 */ strgt tmp3, [dst], #4 /* Return */#ifdef STACK_FRAMES ldmdb fp, {v1, fp, sp, pc}#else /* !STACK_FRAMES */ ldmfd sp!, {v1, pc}#endif /* STACK_FRAMES *//********************************************************************************* bfill - fill a buffer with a specified character** This routine fills the first <nbytes> characters of a buffer with the* character <ch>. Filling is done in the most efficient way possible,* which may be long-word, or even multiple-long-word stores, on some* architectures. In general, the fill will be significantly faster if* the buffer is long-word aligned. (For filling that is restricted to* byte stores, see the manual entry for bfillBytes().)** RETURNS: N/A** NOMANUAL** void bfill* (* char * buf, /@ pointer to buffer @/* int nbytes, /@ number of bytes to fill @/* int ch /@ char with which to fill buffer @/* )*//* Register aliases: gas does not allow redefining symbols as different regs */buf .req r0n_f .req r1ch .req r2FUNC_LABEL(bfill)#ifdef STACK_FRAMES mov ip, sp stmdb sp!, {fp, ip, lr, pc} sub fp, ip, #4#else /* !STACK_FRAMES */ stmfd sp!, {lr} /* Preserve return address */#endif /* STACK_FRAMES */ subs n_f, n_f, #4 /* need at least 4 bytes */ bmi TrailingBytes /* < 4 bytes to go */ /* * word align the dst - first find out how many bytes * must be stored to do this. */ ands tmp3, buf, #3 /* eq means aligned! */ bne AlignDst /* * here when destination is word-aligned, * number of bytes to transfer is (n+4), n is >= 0. */DstAligned: and ch, ch, #0xff /* pad src */ orr ch, ch, ch, ASL #8 orr ch, ch, ch, ASL #16 mov tmp1, ch mov tmp3, ch mov lr, ch subs n_f, n_f, #12-4 /* 12 bytes or more? */ blt TrailingWords subs n_f, n_f, #32-12 /* n+32 to go. */ blt 1f0: stmia buf!, {ch, tmp1, tmp3, lr} stmia buf!, {ch, tmp1, tmp3, lr} subs n_f, n_f, #32 bge 0b /* see if we can handle another 8 */ cmn n_f, #16 stmgeia buf!, {ch, tmp1, tmp3, lr} subge n_f, n_f, #16 /* note that we still have (n+32) bytes to go, and this is <16. */1: /* Here when there are fewer than 16 bytes to go. */ adds n_f, n_f, #32-12 /* (n-12) to go */2: /* Ok - do three words at a time. */ stmgeia buf!, {tmp1, tmp3, lr} subges n_f, n_f, #12 bge 2bTrailingWords: /* (n-12) bytes to go - 0, 1 or 2 words. Check which. */ adds n_f, n_f, #12-4 /* (n-4) to go */ blt TrailingBytes /* < 4 bytes to go */ subs n_f, n_f, #4 strlt ch, [buf], #4 stmgeia buf!, {ch, tmp1} subge n_f, n_f, #4TrailingBytes: /* Here with less than 4 bytes to go */ adds n_f, n_f, #4#ifdef STACK_FRAMES ldmeqdb fp, {fp, sp, pc}#else /* !STACK_FRAMES */ ldmeqfd sp!, {pc} /* 0 bytes, RETURN */#endif /* STACK_FRAMES */ cmp n_f, #2 /* 1, 2 or 3 bytes */ strb ch, [buf], #1 /* 1 */ strgeb ch, [buf], #1 /* 2 */ strgtb ch, [buf], #1 /* 3 */#ifdef STACK_FRAMES ldmdb fp, {fp, sp, pc}#else /* !STACK_FRAMES */ ldmfd sp!, {pc} /* RETURN */#endif /* STACK_FRAMES *//* * word align dst - tmp3 contains current destination * alignment. We can store at least 4 bytes here. */AlignDst: rsb tmp3, tmp3, #4 /* 1-3 bytes to go */ cmp tmp3, #2 strb ch, [buf], #1 /* 1 */ strgeb ch, [buf], #1 /* 2 */ strgtb ch, [buf], #1 /* 3 */ subs n_f, n_f, tmp3 /* check number to go */ blt TrailingBytes /* less than 4 bytes */ b DstAligned/********************************************************************************* bfillBytes - fill buffer with a specified character one byte at a time** This routine fills the first <nbytes> characters of the specified buffer* with the character <ch> one byte at a time. This may be desirable if a* buffer can only be accessed with byte instructions, as in certain* byte-wide memory-mapped peripherals.** RETURNS: N/A** NOMANUAL** void bfillBytes* (* char * buf, /@ pointer to buffer @/* int nbytes, /@ number of bytes to fill @/* int ch /@ char with which to fill buffer @/* )*/FUNC_LABEL(bfillBytes)#ifdef STACK_FRAMES mov ip, sp stmdb sp!, {fp, ip, lr, pc} sub fp, ip, #4#endif /* STACK_FRAMES */ /* Quick check for 0 */ cmp n_f, #0#ifdef STACK_FRAMES ldmeqdb fp, {fp, sp, pc}#else /* !STACK_FRAMES */ moveq pc, lr#endif /* STACK_FRAMES */ /* * The fill loop is rolled out in one loop of 16 byte fills. * It is entered by jumping to the relative location. */ /* Compute jump offset if necessary */ ands tmp1, n_f, #0x0f /* Odd count */ rsbne tmp1, tmp1, #16 /* Offset to jump into */ addne tmp1, pc, tmp1, lsl #2 /* Jump address */ movne pc, tmp1 /* Do the dirty */ /* Loop here while we have > 16 bytes to copy */Fill_Loop: strb ch, [buf], #1 /* 16 */ strb ch, [buf], #1 /* 15 */ strb ch, [buf], #1 /* 14 */ strb ch, [buf], #1 /* 13 */ strb ch, [buf], #1 /* 12 */ strb ch, [buf], #1 /* 11 */ strb ch, [buf], #1 /* 10 */ strb ch, [buf], #1 /* 9 */ strb ch, [buf], #1 /* 8 */ strb ch, [buf], #1 /* 7 */ strb ch, [buf], #1 /* 6 */ strb ch, [buf], #1 /* 5 */ strb ch, [buf], #1 /* 4 */ strb ch, [buf], #1 /* 3 */ strb ch, [buf], #1 /* 2 */ strb ch, [buf], #1 /* 1 */ /* Another iteration */ subs n_f, n_f, #16 /* > 0 (and / 16) if any left */ bgt Fill_Loop /* Another 16 ? */ /* Return */#ifdef STACK_FRAMES ldmdb fp, {fp, sp, pc}#else /* !STACK_FRAMES */ mov pc, lr#endif /* STACK_FRAMES */ #endif /* ! bALib_PORTABLE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -