gfiber / kernel / bruno / baaf0c65bc8ea9c7a404b09bc8cc3b8a1e4f18df / . / arch / metag / lib / memset.S

! Copyright (C) 2008-2012 Imagination Technologies Ltd. | |

.text | |

.global _memset | |

.type _memset,function | |

! D1Ar1 dst | |

! D0Ar2 c | |

! D1Ar3 cnt | |

! D0Re0 dst | |

_memset: | |

AND D0Ar2,D0Ar2,#0xFF ! Ensure a byte input value | |

MULW D0Ar2,D0Ar2,#0x0101 ! Duplicate byte value into 0-15 | |

ANDS D0Ar4,D1Ar1,#7 ! Extract bottom LSBs of dst | |

LSL D0Re0,D0Ar2,#16 ! Duplicate byte value into 16-31 | |

ADD A0.2,D0Ar2,D0Re0 ! Duplicate byte value into 4 (A0.2) | |

MOV D0Re0,D1Ar1 ! Return dst | |

BZ $LLongStub ! if start address is aligned | |

! start address is not aligned on an 8 byte boundary, so we | |

! need the number of bytes up to the next 8 byte address | |

! boundary, or the length of the string if less than 8, in D1Ar5 | |

MOV D0Ar2,#8 ! Need 8 - N in D1Ar5 ... | |

SUB D1Ar5,D0Ar2,D0Ar4 ! ... subtract N | |

CMP D1Ar3,D1Ar5 | |

MOVMI D1Ar5,D1Ar3 | |

B $LByteStub ! dst is mis-aligned, do $LByteStub | |

! | |

! Preamble to LongLoop which generates 4*8 bytes per interation (5 cycles) | |

! | |

$LLongStub: | |

LSRS D0Ar2,D1Ar3,#5 | |

AND D1Ar3,D1Ar3,#0x1F | |

MOV A1.2,A0.2 | |

BEQ $LLongishStub | |

SUB TXRPT,D0Ar2,#1 | |

CMP D1Ar3,#0 | |

$LLongLoop: | |

SETL [D1Ar1++],A0.2,A1.2 | |

SETL [D1Ar1++],A0.2,A1.2 | |

SETL [D1Ar1++],A0.2,A1.2 | |

SETL [D1Ar1++],A0.2,A1.2 | |

BR $LLongLoop | |

BZ $Lexit | |

! | |

! Preamble to LongishLoop which generates 1*8 bytes per interation (2 cycles) | |

! | |

$LLongishStub: | |

LSRS D0Ar2,D1Ar3,#3 | |

AND D1Ar3,D1Ar3,#0x7 | |

MOV D1Ar5,D1Ar3 | |

BEQ $LByteStub | |

SUB TXRPT,D0Ar2,#1 | |

CMP D1Ar3,#0 | |

$LLongishLoop: | |

SETL [D1Ar1++],A0.2,A1.2 | |

BR $LLongishLoop | |

BZ $Lexit | |

! | |

! This does a byte structured burst of up to 7 bytes | |

! | |

! D1Ar1 should point to the location required | |

! D1Ar3 should be the remaining total byte count | |

! D1Ar5 should be burst size (<= D1Ar3) | |

! | |

$LByteStub: | |

SUBS D1Ar3,D1Ar3,D1Ar5 ! Reduce count | |

ADD D1Ar1,D1Ar1,D1Ar5 ! Advance pointer to end of area | |

MULW D1Ar5,D1Ar5,#4 ! Scale to (1*4), (2*4), (3*4) | |

SUB D1Ar5,D1Ar5,#(8*4) ! Rebase to -(7*4), -(6*4), -(5*4), ... | |

MOV A1.2,D1Ar5 | |

SUB PC,CPC1,A1.2 ! Jump into table below | |

SETB [D1Ar1+#(-7)],A0.2 | |

SETB [D1Ar1+#(-6)],A0.2 | |

SETB [D1Ar1+#(-5)],A0.2 | |

SETB [D1Ar1+#(-4)],A0.2 | |

SETB [D1Ar1+#(-3)],A0.2 | |

SETB [D1Ar1+#(-2)],A0.2 | |

SETB [D1Ar1+#(-1)],A0.2 | |

! | |

! Return if all data has been output, otherwise do $LLongStub | |

! | |

BNZ $LLongStub | |

$Lexit: | |

MOV PC,D1RtP | |

.size _memset,.-_memset | |