diff options
author | Ori Bernstein <ori@eigenstate.org> | 2014-08-06 21:20:54 -0400 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2014-08-06 21:22:55 -0400 |
commit | 93809f88c931d6c6dc738b3a9c9f9b463e950e8c (patch) | |
tree | a8c9e15eb274aa81e8a7ea2c845651c7745e501c | |
parent | 4a8b6a32bd2e06a803b203fe90b7b1253e57f362 (diff) | |
download | mc-93809f88c931d6c6dc738b3a9c9f9b463e950e8c.tar.gz |
Add initial cut for freebsd start code.freebsd-port
Mostly, we use %rdi instead of %rsp for the args.
-rw-r--r-- | libstd/start-freebsd.s | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/libstd/start-freebsd.s b/libstd/start-freebsd.s new file mode 100644 index 0000000..5e49c1f --- /dev/null +++ b/libstd/start-freebsd.s @@ -0,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 + |