ref: b678c30f4fea6f5fcb208b23cc24ea4945ec9ec8
parent: 849ce44a08d3f4412c3c37a89edcd7980985ae9a
parent: ae643e101f4a6002d26ffaa28d4f8b8eac3c790e
author: akoshibe <[email protected]>
date: Wed Aug 6 19:14:19 EDT 2014
Merge remote-tracking branch 'origin/freebsd-port'
--- /dev/null
+++ b/libstd/start-freebsd.s
@@ -1,0 +1,123 @@
+.data
+/* std._environment : byte[:][:] */
+.globl std$_environment
+std$_environment:
+.envbase:
+.quad 0 /* env size */
+.envlen:
+.quad 0 /* env ptr */
+
+.globl std$__cenvp
+std$__cenvp:
+.quad 0
+
+.text
+/*
+ * counts the length of the string pointed to
+ * by %r8, returning len in %r9. Does not modify
+ * any registers outside of %r9
+ */
+cstrlen:
+ xorq %r9,%r9
+ jmp .lentest
+
+ .lenloop:
+ incq %r9
+ .lentest:
+ cmpb $0,(%r8,%r9)
+ jne .lenloop
+ ret
+
+
+/*
+ * Counts the size of the null terminated string vector
+ * pointed to by %rbx. Clobbers %r10,%r11
+ */
+count:
+ xorq %r9,%r9
+ movq %rbx,%r11
+.countloop:
+ movq (%r11),%r10
+ testq %r10,%r10
+ jz .countdone
+ addq $1,%r9
+ addq $8,%r11
+ jmp .countloop
+.countdone:
+ ret
+
+/*
+ * iterate over the strings for argc, and put
+ * them into the args array.
+ *
+ * Args:
+ * %rax: holds argc
+ * %rbx: holds argv
+ * %rcx: output destination
+ * Clobbers:
+ * %r8, %r9
+ */
+cvt:
+ jmp .cvttest
+.cvtloop:
+ subq $1,%rax
+ movq (%rbx),%r8
+ call cstrlen
+ movq %r8, (%rcx)
+ movq %r9, 8(%rcx)
+ addq $8, %rbx
+ addq $16, %rcx
+.cvttest:
+ testq %rax,%rax
+ jnz .cvtloop
+.cvtdone:
+ ret
+
+/*
+ * The entry point for the whole program.
+ * This is called by the OS. In order, it:
+ * - Sets up all argc entries as slices
+ * - Sets up all envp entries as slices
+ * - Converts argc/argv to a slice
+ * - Stashes envp in std._environment
+ * - Stashes a raw envp copy in __cenvp (for syscalls to use)
+ * - Calls main()
+ */
+.globl _start
+_start:
+ /* stack allocate sizeof(byte[:])*(argc + len(envp)) */
+ movq (%rdi),%rax
+ leaq 16(%rdi,%rax,8), %rbx /* argp = argv + 8*argc + 8 */
+ call count
+ addq %r9,%rax
+ imulq $16,%rax
+ subq %rax,%rsp
+ movq %rsp, %rdx /* saved args[:] */
+
+ /* convert envp to byte[:][:] for std._environment */
+ movq (%rdi),%rax
+ leaq 16(%rdi,%rax,8), %rbx /* envp = argv + 8*argc + 8 */
+ /* store envp for some syscalls to use without spurious conversion. */
+ movq %rbx,std$__cenvp(%rip)
+ movq %r9,%rax
+ movq %rsp, %rcx
+ movq %r9,.envlen
+ movq %rdx,.envbase
+ call cvt
+ movq %rcx,%rdx
+
+ /* convert argc, argv to byte[:][:] for args. */
+ movq (%rdi), %rax /* argc */
+ leaq 8(%rdi), %rbx /* argv */
+ movq (%rdi), %rsi /* saved argc */
+ call cvt
+ pushq %rsi
+ pushq %rdx
+
+ /* enter the main program */
+ call xmain
+ /* exit(0) */
+ xorq %rdi,%rdi
+ movq $1,%rax
+ syscall
+