diff --git a/.gitignore b/.gitignore index 3fdca0d..0f4f17c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /goas -/babygo +babygo *.o *.bin *.xxd @@ -9,3 +9,6 @@ *.txt *.diff a.out +/out1/* +/out2/* +/out3/* diff --git a/Makefile b/Makefile index b0547c1..cbf1bc8 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,8 @@ goas: $(GO_SOURCES) go build -o goas . .PHONY: test -test: test-single test-multi +# Check /etc/os-release to prevent non-linux from running this +test: /etc/os-release test-single test-babygo-test test-babygo-babygo T1_SOURCES = $(wildcard t1/*.s) T1_GNU_OBJS = $(T1_SOURCES:t1/%.s=out1/%.gnu.o) @@ -35,41 +36,40 @@ out1/%.gnu.o: t1/%.s out1 out1/%.my.o: t1/%.s goas out1 ./goas -o $@ $< -# Test multi-source program -.PHONY: test-multi test-babygo-test test-babygo-self -test-multi: test-babygo-test test-babygo-self + +# Test asm files generated by babygo's test +test-babygo-test: out2/my.o out2/gnu.o + diff $^ out2: mkdir -p $@ -test-babygo-test: out2/t.my.o out2/t.gnu.o - diff $^ - -out2/t.gnu.o: t2/babygo-runtime.s t2/babygo-test.s - as -o $@ $^ +out2/gnu.o: out2 t2/babygo-runtime.s t2/babygo-test.s + as -o $@ t2/babygo-runtime.s t2/babygo-test.s -out2/t.my.o: goas t2/babygo-runtime.s t2/babygo-test.s out2 +out2/my.o: goas out2 t2/babygo-runtime.s t2/babygo-test.s ./goas -o $@ t2/babygo-runtime.s t2/babygo-test.s -test-babygo-self: out2/b.my.o out2/b.gnu.o + +# Test asm files generated by babygo's self compiling +test-babygo-babygo: out3/my.o out3/gnu.o diff $^ -out2/b.my.o: goas t2/babygo-runtime.s t2/babygo-main.s - ./goas -o $@ t2/babygo-runtime.s t2/babygo-main.s +out3: + mkdir -p $@ -out2/b.gnu.o: t2/babygo-runtime.s t2/babygo-main.s - as -o $@ $^ +out3/my.o: goas out3 t3/babygo-runtime.s t3/babygo-main.s + ./goas -o $@ t3/babygo-runtime.s t3/babygo-main.s -# Make binary executables (These are not essential) -out2/t.gnu.bin: t2/t.gnu.o - ld -o $@ $< +out3/gnu.o: out3 t3/babygo-runtime.s t3/babygo-main.s + as -o $@ t3/babygo-runtime.s t3/babygo-main.s -out2/t.my.bin: t2/t.my.o - ld -o $@ $< +# Make and run babygo +run-babygo: babygo + ./$< version -babygo: out2/b.my.o +babygo: out3/my.o ld -o $@ $< - ./$@ version clean: - rm -f goas *.{o,bin,out} out{1,2}/*.{o,bin} + rm -f goas *.{o,bin,out} out{1,2}/* ./babygo diff --git a/t2/babygo-main.s b/t3/babygo-main.s similarity index 100% rename from t2/babygo-main.s rename to t3/babygo-main.s diff --git a/t3/babygo-runtime.s b/t3/babygo-runtime.s new file mode 100644 index 0000000..1ee5958 --- /dev/null +++ b/t3/babygo-runtime.s @@ -0,0 +1,98 @@ +# runtime.s +.text + +# shortcut entrypoint to simplify linker invocation +.global _start +_start: + jmp _rt0_amd64_linux + +# Start of the program +# (runtime/rt0_linux_amd64.s) +.global _rt0_amd64_linux +_rt0_amd64_linux: + jmp _rt0_amd64 + +# (runtime/asm_amd64.s) +_rt0_amd64: + movq 0(%rsp), %rdi # argc + leaq 8(%rsp), %rsi # argv + jmp runtime.rt0_go + +# (runtime/asm_amd64.s) +runtime.rt0_go: + movq %rdi, %rax # argc + movq %rsi, %rbx # argv + movq %rbx, runtime.__argv__+0(%rip) # ptr + movq %rax, runtime.__argv__+8(%rip) # len + movq %rax, runtime.__argv__+16(%rip) # cap + + movq %rdi, %rax # argc + imulq $8, %rax # argc * 8 + addq %rsp, %rax # stack top addr + (argc * 8) + addq $16, %rax # + 16 (skip null and go to next) => envp + movq %rax, runtime.envp+0(%rip) # envp + + callq runtime.heapInit + + callq runtime.__initGlobals + callq runtime.envInit + + callq main.__initGlobals + + callq os.init # set os.Args + callq main.main + + movq $0, %rdi # status 0 + movq $60, %rax # sys_exit + syscall + # End of program + +// func Write(fd int, p []byte) int +runtime.Write: + movq 8(%rsp), %rax # arg0:fd + movq 16(%rsp), %rdi # arg1:ptr + movq 24(%rsp), %rsi # arg2:len + subq $8, %rsp + pushq %rsi + pushq %rdi + pushq %rax + pushq $1 # sys_write + callq syscall.Syscall + addq $8 * 4, %rsp # reset args area + popq %rax # retval + movq %rax, 32(%rsp) # r0 int + ret + +runtime.printstring: + movq 8(%rsp), %rdi # arg0:ptr + movq 16(%rsp), %rsi # arg1:len + subq $8, %rsp + pushq %rsi + pushq %rdi + pushq $2 # stderr + pushq $1 # sys_write + callq syscall.Syscall + addq $8 * 4, %rsp + popq %rax # retval + ret + +// func Syscall(trap, a1, a2, a3 uintptr) uintptr +runtime.Syscall: + movq 8(%rsp), %rax # syscall number + movq 16(%rsp), %rdi # arg0 + movq 24(%rsp), %rsi # arg1 + movq 32(%rsp), %rdx # arg2 + syscall + movq %rax, 40(%rsp) # r0 uintptr + ret + +// func Syscall(trap, a1, a2, a3 uintptr) uintptr +syscall.Syscall: + movq 8(%rsp), %rax # syscall number + movq 16(%rsp), %rdi # arg0 + movq 24(%rsp), %rsi # arg1 + movq 32(%rsp), %rdx # arg2 + syscall + movq %rax, 40(%rsp) # r0 uintptr + ret +