aboutsummaryrefslogtreecommitdiff
path: root/include/primops.s
diff options
context:
space:
mode:
Diffstat (limited to 'include/primops.s')
-rw-r--r--include/primops.s54
1 files changed, 54 insertions, 0 deletions
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