aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/data.s99
-rw-r--r--include/intops.s25
-rw-r--r--include/io.s44
-rw-r--r--include/listops.s40
-rw-r--r--include/macros.s43
-rw-r--r--include/main_exit.s10
-rw-r--r--include/primops.s54
-rw-r--r--include/uskel.s54
8 files changed, 369 insertions, 0 deletions
diff --git a/include/data.s b/include/data.s
new file mode 100644
index 0000000..8261881
--- /dev/null
+++ b/include/data.s
@@ -0,0 +1,99 @@
+
+.ifndef _data_s_file
+_data_s_file:
+
+# Simple values and boxed machine integers
+# | ptr | value |
+CON_evacuate1:
+ retq
+CON_scavenge1:
+ add $0x10, %rsi
+ retq
+INT_info_table:
+ cell CON_evacuate1
+ cell CON_scavenge1
+ cell 0
+INT_code:
+ continue
+
+# List
+# | ptr | 0 |
+# | ptr | 1 | a | b |
+LIST_evacuate:
+ # [] | a : b
+ retq #TODO
+LIST_scavenge:
+ mov 0x8(%rbp), %rax
+ shl $1, %rax
+ add $2, %rax
+ shl $3, %rax
+ add %rax, %rsi
+ retq
+LIST_info_table:
+ cell LIST_evacuate
+ cell LIST_scavenge
+ cell 0
+LIST_code:
+ continue
+
+# FUN/PAP combo objects
+# | ptr | thunkptr | args | arg[0] | arg[1] | ... | arg[args] |
+FUN_evacuate:
+ retq #TODO
+FUN_scavenge:
+ mov 0x10(%rbp), %rax
+ add $3, %rax
+ shl $3, %rax
+ add %rax, %rsi
+ retq
+
+# Simple info for n-ary functions
+# TODO continue to add as required
+fun1_info_table:
+ cell FUN_evacuate
+ cell FUN_scavenge
+ cell 1
+fun1_code:
+ continue
+
+fun2_info_table:
+ cell FUN_evacuate
+ cell FUN_scavenge
+ cell 2
+fun2_code:
+ continue
+
+fun3_info_table:
+ cell FUN_evacuate
+ cell FUN_scavenge
+ cell 3
+fun3_code:
+ continue
+
+# indirection (Q: how to recognize IND and THUNK on return?)
+# | ptr | indptr |
+IND_evacuate:
+ retq #TODO
+IND_scavenge:
+ add $0x10,%rsi
+ retq
+IND_info:
+ cell IND_evacuate
+ cell IND_scavenge
+ cell 0
+IND_code:
+ enter 0x8(%rbp)
+
+# THU objects (gc implementation only, actual THUs are defined by functions)
+# | ptr | args | arg[0] | arg[1] | ... | arg[args] |
+# args wouldn't need to be here but let's keep them for gc simplicity
+THU_evacuate:
+ retq #TODO
+THU_scavenge:
+ mov 0x8(%rbp), %rax
+ add $2,%rax
+ shl $3,%rax
+ add %rax,%rsi
+ retq
+
+.endif # _data_s_file
diff --git a/include/intops.s b/include/intops.s
new file mode 100644
index 0000000..dbadb37
--- /dev/null
+++ b/include/intops.s
@@ -0,0 +1,25 @@
+
+.ifndef _intops_s_file
+_intops_s_file:
+
+.include "include/primops.s"
+
+.primop2 plus
+ mov 010(%rsi), %rax # arg 2
+ mov 020(%rbp), %rsi # location of arg1
+ add 010(%rsi), %rax # arg 1
+ primop2_ret_int %rax
+
+.primop2 mul
+ mov 010(%rsi), %rax # arg 2
+ mov 020(%rbp), %rsi # location of arg1
+ mulq 010(%rsi) # arg 1 (goes to %rax and %rdx)
+ primop2_ret_int %rax
+
+.primop2 sub
+ mov 020(%rbp), %rdi # location of arg1
+ mov 010(%rdx), %rax # arg 1
+ sub 010(%rsi), %rax # arg 2
+ primop2_ret_int %rax
+
+.endif # _intops_s_file
diff --git a/include/io.s b/include/io.s
new file mode 100644
index 0000000..c348e7f
--- /dev/null
+++ b/include/io.s
@@ -0,0 +1,44 @@
+
+.ifndef _io_s_file
+_io_s_file:
+
+# | int | -> cont
+.thunkcode print
+ push %rsi
+ push %rbp
+ pushq $2
+ pushq $print_fini
+
+ mov %rsp, %rsi
+ enter 020(%rbp)
+
+# arg -> | ret | cont |
+.thunkcode print_fini
+ mov 010(%rsi), %rax
+
+ # make a string
+ mov %rsp, %r15
+ sub $1, %r15
+ movb $0x0a, (%r15)
+ print_fini_next:
+ mov %al, %bl
+ and $1, %bl
+ add $0x30, %bl
+ sub $1, %r15
+ movb %bl, (%r15)
+ shr $1, %rax
+ jnz print_fini_next
+
+ mov $0, %rdi #stdin
+ mov %rsp, %rdx
+ sub %r15, %rdx #size
+ mov %r15, %rsi #buf
+ mov $1, %rax #write
+ syscall
+
+ mov 020(%rbp), %rsi
+ movq $0, 010(%rsi)
+ movq $INT_code, 0(%rsi)
+ enter 030(%rbp)
+
+.endif # _io_s_file
diff --git a/include/listops.s b/include/listops.s
new file mode 100644
index 0000000..eb8f6cf
--- /dev/null
+++ b/include/listops.s
@@ -0,0 +1,40 @@
+
+.ifndef _listops_s_file
+_listops_s_file:
+
+.include "include/primops.s"
+
+# | n | list | -> cont
+.primop2 list_int_index
+ mov 010(%rsi), %rdx # the list constructor id, must be 1
+ cmp $1, %rdx
+ jne list_int_index_not_found
+
+ mov 020(%rbp), %rcx
+ mov 010(%rcx), %rcx
+ test %rcx, %rcx
+ jz list_int_index_found #we are taking 0, all happy, return it
+
+ #more probably we need to continue, make replacement thunks
+ sub $1, %rcx
+ pushq %rcx
+ pushq $INT_code
+ mov %rsp, %r11
+
+ pushq 030(%rsi) # tail
+ push %r11
+ pushq $2
+ pushq $list_int_index
+ mov %rsp, %r11
+
+ primop2_cont_indirect %r11
+
+list_int_index_not_found:
+ movq 0, %rax #fault
+
+list_int_index_found:
+ mov 020(%rsi), %rax #head
+ primop2_cont_indirect %rax
+
+
+.endif # _listops_s_file
diff --git a/include/macros.s b/include/macros.s
new file mode 100644
index 0000000..d915171
--- /dev/null
+++ b/include/macros.s
@@ -0,0 +1,43 @@
+
+.ifndef _macros_s_file
+_macros_s_file:
+
+.macro enter_rbp
+ jmp *(%rbp)
+.endm
+
+.macro enter x
+ mov \x, %rbp
+ enter_rbp
+.endm
+
+.macro cell x
+ .quad \x
+.endm
+
+.macro continue
+ mov %rsi, %rax
+ mov %rbp, %rsi
+ enter %rax
+.endm
+
+.macro thunkenv arg, dest
+ mov (8*(\arg+2))(%rbp), \dest
+.endm
+
+.macro enter_thunkenv arg
+ mov (8*(\arg+2))(%rbp), %rbp
+ jmp *(%rbp)
+.endm
+
+# this needs data.s
+.macro .thunkcode name
+ .align 8
+ __\name\()_info:
+ cell THU_evacuate
+ cell THU_scavenge
+ cell 0
+ \name:
+.endm
+
+.endif # _macros_s_file
diff --git a/include/main_exit.s b/include/main_exit.s
new file mode 100644
index 0000000..a38c5e5
--- /dev/null
+++ b/include/main_exit.s
@@ -0,0 +1,10 @@
+.ifndef _main_exit_s_file
+_main_exit_s_file:
+
+# exitcode -> | cont (unused, should be 0) |
+.thunkcode main_exit
+ mov 0x8(%rsi), %rdi # result to syscall exitcode
+ mov $0x3c, %rax # syscall 60
+ syscall # exit %rdi
+
+.endif # _main_exit_s_file
diff --git a/include/primops.s b/include/primops.s
new file mode 100644
index 0000000..bcb835f
--- /dev/null
+++ b/include/primops.s
@@ -0,0 +1,54 @@
+
+.ifndef _primops_s_file
+_primops_s_file:
+
+.include "include/data.s"
+
+.macro .primop2 name
+# | arg1 | arg2 | -> cont
+.thunkcode \name
+ # push a thunk for finishing the plus
+ push %rsi # cont
+ push %rbp # ret (self)
+ pushq 030(%rbp)
+ pushq $3
+ pushq $\name\()_step1
+
+ mov %rsp, %rsi # continue to the new thunk
+ enter 0x10(%rbp) # evaluate arg1
+
+# arg1 -> | arg2 | ret | cont |
+.thunkcode \name\()_step1
+ # this is guaranteed to be entered only once (it's a cont), so we can rewrite the thunk in place
+ mov 020(%rbp), %rax
+ movq $\name\()_fini, 0(%rbp)
+ mov %rsi, 020(%rbp)
+
+ mov %rbp, %rsi # continue on the rewritten thunk
+ enter %rax # evaluate arg1
+
+# arg2 -> | arg1 | ret | cont |
+.thunkcode \name\()_fini
+ # at this point,
+ # arg1 is pointed to by 020(%rbp)
+ # arg2 is pointed to by %rsi
+.endm
+
+.macro primop2_ret_int val
+ # the result should now be in %rax
+ mov 030(%rbp), %rsi # save result to the original plus thunk
+ movq \val, 010(%rsi)
+ movq $INT_code, 0(%rsi)
+
+ enter 040(%rbp) # eval cont, returning %rsi
+.endm
+
+.macro primop2_cont_indirect new
+ mov 030(%rbp), %rdi # load the original thunk
+ mov 040(%rbp), %rsi # set the continuation
+ movq \new, 010(%rdi) # set the indirect to the new thunk
+ movq $IND_code, 0(%rdi)
+ enter \new # continue evaluating the new thunk
+.endm
+
+.endif # _primops_s_file
diff --git a/include/uskel.s b/include/uskel.s
new file mode 100644
index 0000000..136b382
--- /dev/null
+++ b/include/uskel.s
@@ -0,0 +1,54 @@
+
+# uskel runtime and start; include this at the top.
+
+.section .init
+.global _start
+_start:
+ jmp _uskel_start
+
+.include "include/macros.s"
+
+.section .bss
+_memory_state:
+ cell 0 # bottom of allocation (grows down)
+ cell 0 # region start
+ cell 0 # region end
+ cell 0 # program entry rsp (aka the actual stack)
+
+.section .text
+
+_uskel_alloc_basic_mem:
+ mov $0x100000, %r15 # desired size
+
+ mov $0x9, %rax # mmap
+ mov $0, %rdi # addr = NULL
+ mov %r15, %rsi # len = %rcx
+ mov $0x3, %rdx # prot = PROT_READ 0x1 | PROT_WRITE 0x2
+ mov $0x22, %r10 # flags = MAP_PRIVATE 0x2 | MAP_ANONYMOUS 0x20
+ mov $-1, %r8 # fd = -1
+ mov $0, %r9 # off = 0
+ syscall
+ mov $_memory_state, %rdi
+ mov %rax, 010(%rdi)
+ add %r15, %rax
+ mov %rax, (%rdi)
+ mov %rax, 020(%rdi)
+ retq
+
+_uskel_start:
+ call _uskel_alloc_basic_mem
+ # use the stack pointer for easy writing to the heap,
+ # but back it up to memory state
+ mov $_memory_state, %rdi
+ mov %rsp, 030(%rdi)
+ mov 0(%rdi), %rsp
+
+ # push a thunk for main
+ pushq $0
+ pushq $main
+
+ mov $0, %rsi # set continuation to exit
+ enter %rsp # run the program
+ # Q: are there gonna be functions that have both the argument AND the cont?
+ # A: No, stuff is either entered as return-continuation (takes res, cont has to be saved) or as forward call (takes cont)
+ # (needs validation)