.ifndef _primops_s_file
_primops_s_file:

.include "include/data.s"

# TODO: try to generalize the returning macros

.macro .primop1 name
# | arg1 | -> cont
.thunkcode \name
	needs_alloc $040
	# push a thunk for collecting the first arg and set it as continuation
	thunkto %rsi, $\name\()_fini, $2, %rbp, %rsi
	enter 020(%rbp) # evaluate arg1

# arg1 -> | ret | cont |
.thunkcode \name\()_fini
	# at this point arg1 is pointed to by %rsi
.endm

.macro primop1_ret_int val
	# the result should now be in %rax
	mov 020(%rbp), %rsi # save result to the original primop2 thunk (we don't need IND)
	movq \val, 010(%rsi)
	movq $INT_code, 0(%rsi)

	enter 030(%rbp) # eval cont, returning %rsi
.endm

.macro primop1_cont_indirect new
	mov 020(%rbp), %rdi # load the original thunk
	mov 030(%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


.macro .primop2 name
# | arg1 | arg2 | -> cont
.thunkcode \name
	needs_alloc $050
	# push a thunk for collecting the first arg and set it as continuation
	thunkto %rsi, $\name\()_step1, $3, 030(%rbp), %rbp, %rsi
	enter 020(%rbp) # evaluate arg1

# arg1 -> | arg2 | ret | cont |
.thunkcode \name\()_step1
	# this is guaranteed to be entered only once (it's a case cont), so we
	# can rewrite the thunk in place
	xchg %rsi, 020(%rbp) # store arg1, get arg 2
	movq $\name\()_fini, 0(%rbp) # continue with finishing

	xchg %rbp, %rsi # continue here, evaluate arg 2
	enter_rbp

# 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
	# TODO: try to generalize
	# the result should now be in %rax
	mov 030(%rbp), %rsi # save result to the original primop2 thunk
	movq \val, 010(%rsi)
	movq $INT_code, 0(%rsi)

	enter 040(%rbp) # eval cont, returning %rsi
.endm

.macro primop2_cont_indirect new
	# TODO: try to generalize
	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