]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/libc/amd64/memmove.s
libc and ape support for amd64
[plan9front.git] / sys / src / libc / amd64 / memmove.s
diff --git a/sys/src/libc/amd64/memmove.s b/sys/src/libc/amd64/memmove.s
new file mode 100644 (file)
index 0000000..1f00537
--- /dev/null
@@ -0,0 +1,81 @@
+TEXT memmove(SB), $0
+       MOVQ    RARG, DI
+       MOVQ    DI, AX                  /* return value */
+       MOVQ    p2+8(FP), SI
+       MOVL    n+16(FP), BX
+       CMPL    BX, $0
+       JGT     _ok
+       JEQ     _return                 /* nothing to do if n == 0 */
+       MOVL    $0, SI                  /* fault if n < 0 */
+
+/*
+ * check and set for backwards:
+ *     (p2 < p1) && ((p2+n) > p1)
+ */
+_ok:
+       CMPQ    SI, DI
+       JGT     _forward
+       JEQ     _return                 /* nothing to do if p2 == p1 */
+       MOVQ    SI, DX
+       ADDQ    BX, DX
+       CMPQ    DX, DI
+       JGT     _back
+
+/*
+ * copy whole longs if aligned
+ */
+_forward:
+       CLD
+       MOVQ    SI, DX
+       ORQ     DI, DX
+       ANDL    $3, DX
+       JNE     c3f
+       MOVQ    BX, CX
+       SHRQ    $2, CX
+       ANDL    $3, BX
+       REP;    MOVSL
+
+/*
+ * copy the rest, by bytes
+ */
+       JEQ     _return                 /* flags set by above ANDL */
+c3f:
+       MOVL    BX, CX
+       REP;    MOVSB
+
+       RET
+
+/*
+ * whole thing backwards has
+ * adjusted addresses
+ */
+_back:
+       ADDQ    BX, DI
+       ADDQ    BX, SI
+       STD
+       SUBQ    $4, DI
+       SUBQ    $4, SI
+/*
+ * copy whole longs, if aligned
+ */
+       MOVQ    DI, DX
+       ORQ     SI, DX
+       ANDL    $3, DX
+       JNE     c3b
+       MOVL    BX, CX
+       SHRQ    $2, CX
+       ANDL    $3, BX
+       REP;    MOVSL
+/*
+ * copy the rest, by bytes
+ */
+       JEQ     _return                 /* flags set by above ANDL */
+
+c3b:
+       ADDQ    $3, DI
+       ADDQ    $3, SI
+       MOVL    BX, CX
+       REP;    MOVSB
+
+_return:
+       RET