code: 9ferno

ref: b548687a8ed1d0a159c9d3f3f921d93bbb56908e
dir: /os/pc64/bindings.s/

View raw version

/*
This file is the forth equivalent of os/port/inferno.c
	It contains forth bindings for the functions in os/port/sysfile.c
 */
/*
plan9 assembler puts the first argument in R8 (RARG), return value in AX.
	Caller saves registers - plan9 convention
	not maintaining the values of the temporary registers or EFLAGS
*/
/*
using
	( 2nd_parameter 1st_parameter -- )	mode fd open
		simpler code, more comprehensible with the 1st arg next to the call - my opinion
instead of
	( 1st_parameter 2nd_parameter -- ) 	fd mode open
might revisit this later after a trial

there is no forth word for this. It is call'able by the bindings subroutines
cannot get this to work and I cannot decipher it with all the psuedo register nonsense
*/
//TEXT	ff_to_c(SB), $0	/* ( argn .. arg2 arg1 nargs -- ) (G move args to C stack) */
//	POPQ SI			/* get my return PC from the stack */
//	MOVQ TOP, CX	/* check nargs */
//	POP(TOP)
//	TESTQ $0, CX
//	JZ .ff_to_c_done /* no args */
//	MOVQ TOP, RARG	/* 1st argument is put in RARG also */
//.ff_to_c_again:
//	PUSHQ TOP
//	POP(TOP)
//	LOOP .ff_to_c_again
//.ff_to_c_done:
//	STOREFORTH
//	JMP* SI /* go back to the caller */

#define STORE(x,y) \
	MOVQ $y, CX; \
	ADDQ UP, CX; \
	MOVQ x, 0(CX);

#define	STOREFORTH \
	STORE(TOP,FORTHTOP);\
	STORE(PSP,FORTHPSP);\
	STORE(RSP,FORTHRSP);\
	STORE(IP,FORTHIP);\
	STORE(W,FORTHW);\
	STORE(UP,FORTHUP);\
	STORE(UPE,FORTHUPE);

#define RESTORE(x,y) \
	MOVQ $x, CX; \
	ADDQ UP, CX; \
	MOVQ 0(CX), y;

#define RESTOREFORTH \
	RESTORE(FORTHTOP,TOP);\
	RESTORE(FORTHPSP,PSP);\
	RESTORE(FORTHRSP,RSP);\
	RESTORE(FORTHIP,IP);\
	RESTORE(FORTHW,W);\
	RESTORE(FORTHUP,UP);\
	RESTORE(FORTHUPE,UPE);

#define C_TO_F_0 \
	RESTOREFORTH;

#define C_TO_F_1 /* there is a returned argument */\
	C_TO_F_0; \
	PUSH(TOP); \
	MOVQ AX, TOP;	/* C puts the return value in AX */\

#define F_TO_C_3 \
	MOVQ TOP, 16(SP);\
	POP(TOP);\
	MOVQ TOP, 8(SP);\
	POP(TOP);\
	MOVQ TOP, RARG;\
	POP(TOP);\
	STOREFORTH;

#define F_TO_C_2 \
	MOVQ TOP, 8(SP);\
	POP(TOP);\
	MOVQ TOP, RARG;\
	POP(TOP);\
	STOREFORTH;

#define F_TO_C_1 \
	MOVQ TOP, RARG;\
	POP(TOP);\
	STOREFORTH;

TEXT	sysopen(SB), 1, $24	/* ( cstr mode -- fd ) */
	MOVQ UP, 16(SP)
	F_TO_C_2
	CALL kopen(SB)
	MOVQ 16(SP), UP
	C_TO_F_1
	ADDQ $24, SP
	NEXT

TEXT	sysclose(SB), 1, $16	/* ( fd -- n ) */
	MOVQ UP, 8(SP)
	F_TO_C_1
	CALL kclose(SB)
	MOVQ 24(SP), UP
	C_TO_F_1
	ADDQ $16, SP
	NEXT

/*
 * no link register in amd64
 * 3 arguments for kwrite = 24 bytes
 * 1 local for storing UP = 8 bytes
 * 1 local for storing fd
 * Hence, need 40 bytes on the stack
 * if fd == 0 and read return value == 0 == End of file, terminate
 */
	PUSH(TOP)		/* ( fd a n n ) */
	MOVQ 8(PSP), CX	/*  CX = a  ( fd a n n ) */
	PUSH(CX)		/* ( fd a n a n ) */

	CALL validatebuffer(SB)	/* ( fd a n a n -- fd a n ) */

#define CHECKBUFFER	\
	MOVQ TOP, CX; \
	CMPQ CX, $0;	/* negative n? */\
	JLT belowup;	/* TODO have an appropriate error message */\
	ADDQ (PSP), CX;	/* CX = a+n */\
	CMPQ CX, UPE;	/* a+n, UPE */\
	JGT aboveupe;	/* a+n > UPE */\
	CMPQ (PSP), UP;	/* a, UP */\
	JLT belowup;	/* a < UP */

TEXT	sysread(SB), 1, $40	/* ( fd a n -- n2 ) */

	CHECKBUFFER;

	MOVQ 8(PSP), CX
	MOVQ CX, 32(SP)	/* storing the fd to double check later */
	MOVQ UP, 24(SP)
	F_TO_C_3
	CALL kread(SB)
	MOVQ 24(SP), UP
	C_TO_F_1

	CMPQ TOP, $-1		/* return value == -1? */
	JEQ fsread_checkfd	/* return value = -1 */
	TESTQ TOP, TOP		/* check if read return value == 0 */
	JNZ fsread_continue
fsread_checkfd:
	MOVQ 32(SP), CX		/* read return value == 0, check if fd is stdin */
	TESTQ CX, CX
	JNZ fsread_continue

	/* and fd == 0, terminate */
	ADDQ $40, SP
	JMP _fthterminate

fsread_continue:
	ADDQ $40, SP
	NEXT

/*
 * no link register in amd64
 * 3 arguments for kwrite = 24 bytes
 * 1 local for storing UP = 8 bytes
 * Hence, need 32 bytes on the stack
 */
TEXT	syswrite(SB), 1, $32	/* ( fd a n -- n2|-1 ) */

	CHECKBUFFER

	MOVQ UP, 24(SP)
	F_TO_C_3
	CALL kwrite(SB)
	MOVQ 24(SP), UP
	C_TO_F_1
	ADDQ $32, SP
	NEXT

TEXT	sysseek(SB), 1, $32	/* ( fd pos type -- n ) */
	MOVQ UP, 24(SP)
	F_TO_C_3
	CALL kseek(SB)
	MOVQ 24(SP), UP
	C_TO_F_1
	ADDQ $32, SP
	NEXT

TEXT	syscreate(SB), 1, $32	/* ( cstr mode perm -- fd ) */
	MOVQ UP, 24(SP)
	F_TO_C_3
	CALL kcreate(SB)
	MOVQ 24(SP), UP
	C_TO_F_1
	ADDQ $32, SP
	NEXT

TEXT	sysbind(SB), 1, $32	/* ( cstrold cstrnew flags -- int ) */
	MOVQ UP, 24(SP)
	F_TO_C_3
	CALL kbind(SB)
	MOVQ 24(SP), UP
	C_TO_F_1
	ADDQ $32, SP
	NEXT

#define F_TO_C_5 \
	MOVQ TOP, 32(SP);\
	POP(TOP);\
	MOVQ TOP, 24(SP);\
	POP(TOP);\
	MOVQ TOP, 16(SP);\
	POP(TOP);\
	MOVQ TOP, 8(SP);\
	POP(TOP);\
	MOVQ TOP, RARG;\
	POP(TOP);\
	STOREFORTH;

TEXT	sysmount(SB), 1, $48	/* ( fd afd cstrold flags spec -- int ) */
	MOVQ UP, 40(SP)
	F_TO_C_5
	CALL kmount(SB)
	MOVQ 40(SP), UP
	C_TO_F_1
	ADDQ $48, SP
	NEXT