diff options
Diffstat (limited to 'src/misc.S')
-rw-r--r-- | src/misc.S | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/src/misc.S b/src/misc.S new file mode 100644 index 0000000..596daf5 --- /dev/null +++ b/src/misc.S @@ -0,0 +1,179 @@ +@ vim:filetype=armasm + +@ Generic memory routines. +@ (c) Copyright 2007, Grazvydas "notaz" Ignotas + + +.global memcpy16 @ unsigned short *dest, unsigned short *src, int count + +memcpy16: + eor r3, r0, r1 + tst r3, #2 + bne mcp16_cant_align + + tst r0, #2 + ldrneh r3, [r1], #2 + subne r2, r2, #1 + strneh r3, [r0], #2 + + subs r2, r2, #4 + bmi mcp16_fin + +mcp16_loop: + ldmia r1!, {r3,r12} + subs r2, r2, #4 + stmia r0!, {r3,r12} + bpl mcp16_loop + +mcp16_fin: + tst r2, #2 + ldrne r3, [r1], #4 + strne r3, [r0], #4 + ands r2, r2, #1 + bxeq lr + +mcp16_cant_align: + ldrh r3, [r1], #2 + subs r2, r2, #1 + strh r3, [r0], #2 + bne mcp16_cant_align + + bx lr + + + +@ 0x12345678 -> 0x34127856 +@ r4=temp, lr=0x00ff00ff +.macro bswap reg + and r4, \reg, lr + and \reg, lr, \reg, lsr #8 + orr \reg, \reg, r4, lsl #8 +.endm + + +@ dest must be halfword aligned, src can be unaligned +.global memcpy16bswap @ unsigned short *dest, void *src, int count + +memcpy16bswap: + tst r1, #1 + bne mcp16bs_cant_align2 + + eor r3, r0, r1 + tst r3, #2 + bne mcp16bs_cant_align + + tst r0, #2 + beq mcp16bs_aligned + ldrh r3, [r1], #2 + sub r2, r2, #1 + orr r3, r3, r3, lsl #16 + mov r3, r3, lsr #8 + strh r3, [r0], #2 + +mcp16bs_aligned: + stmfd sp!, {r4,lr} + mov lr, #0xff + orr lr, lr, lr, lsl #16 + + subs r2, r2, #4 + bmi mcp16bs_fin4 + +mcp16bs_loop: + ldmia r1!, {r3,r12} + subs r2, r2, #4 + bswap r3 + bswap r12 + stmia r0!, {r3,r12} + bpl mcp16bs_loop + +mcp16bs_fin4: + tst r2, #2 + beq mcp16bs_fin2 + ldr r3, [r1], #4 + bswap r3 + str r3, [r0], #4 + +mcp16bs_fin2: + ldmfd sp!, {r4,lr} + ands r2, r2, #1 + bxeq lr + +mcp16bs_cant_align: + ldrh r3, [r1], #2 + subs r2, r2, #1 + orr r3, r3, r3, lsl #16 + mov r3, r3, lsr #8 + strh r3, [r0], #2 + bne mcp16bs_cant_align + bx lr + + @ worst case +mcp16bs_cant_align2: + ldrb r3, [r1], #1 + ldrb r12,[r1], #1 + subs r2, r2, #1 + mov r3, r3, lsl #8 + orr r3, r3, r12 + strh r3, [r0], #2 + bne mcp16bs_cant_align2 + bx lr + + + +.global memcpy32 @ int *dest, int *src, int count + +memcpy32: + stmfd sp!, {r4,lr} + + subs r2, r2, #4 + bmi mcp32_fin + +mcp32_loop: + ldmia r1!, {r3,r4,r12,lr} + subs r2, r2, #4 + stmia r0!, {r3,r4,r12,lr} + bpl mcp32_loop + +mcp32_fin: + tst r2, #3 + ldmeqfd sp!, {r4,pc} + tst r2, #1 + ldrne r3, [r1], #4 + strne r3, [r0], #4 + +mcp32_no_unal1: + tst r2, #2 + ldmneia r1!, {r3,r12} + ldmfd sp!, {r4,lr} + stmneia r0!, {r3,r12} + bx lr + + + +.global memset32 @ int *dest, int c, int count + +memset32: + stmfd sp!, {lr} + + mov r3, r1 + subs r2, r2, #4 + bmi mst32_fin + + mov r12,r1 + mov lr, r1 + +mst32_loop: + subs r2, r2, #4 + stmia r0!, {r1,r3,r12,lr} + bpl mst32_loop + +mst32_fin: + tst r2, #1 + strne r1, [r0], #4 + + tst r2, #2 + stmneia r0!, {r1,r3} + + ldmfd sp!, {pc} + + |