Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / arch / metag / lib / memset.S
diff --git a/kernel/arch/metag/lib/memset.S b/kernel/arch/metag/lib/memset.S
new file mode 100644 (file)
index 0000000..721085b
--- /dev/null
@@ -0,0 +1,86 @@
+!   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
+