ref: 5904f303924ad043240d56ee1875a5f8a1916afc
parent: 6b9b01c4efb785704a8a5bff92d11250cb284c11
author: 9ferno <gophone2015@gmail.com>
date: Sat Oct 30 04:23:47 EDT 2021
working rudimentary c ffi
--- a/os/pc64/ff.s
+++ b/os/pc64/ff.s
@@ -1,6 +1,12 @@
#include "mem.h"
/*
+
+The bigger goal is to replace the dis vm with ff
+ff outputs to screen now.
+But, the input needs to be fixed.
+make this into a devff like device that reads commands and outputs the result.
+
ff kernel, amd64 9front variant
Register usage:
@@ -7,13 +13,14 @@
TOS: AX top of stack register
SP: SP parameter stack pointer, grows towards lower memory (downwards)
- RP: BP return stack pointer, grows towards higher memory (upwards)
+ RP: BP (= RARG) return stack pointer, grows towards higher memory (upwards)
AP: SI address pointer
W: DI work register (holds CFA)
BX, CX, DX, R8-R15 temporary registers
-Memory map:
+plan9 assembler puts the first argument in BP (RARG), return value in AX.
+Memory map:
Return stack 4096 bytes at FFSTART
|
|
@@ -43,6 +50,103 @@
*/
#include "primitives.s"
+/*
+plan9 assembler puts the first argument in BP (RARG), return value in AX.
+ For calling a C function with a parameter:
+ Store AX somewhere
+ POPQ AX
+ PUSHA
+ Store ff's SP
+ Restore C's SP
+ POPA -- this should not be needed as C is caller save
+ MOVQ from somewhere to BP
+ -- call the c function
+ For calling a C function without a parameter:
+ PUSHA
+ Store ff's SP
+ Restore C's SP
+ POPA -- this should not be needed as C is caller save
+ -- call the c function
+ For coming back from a C function: -- ignoring the return value
+ PUSHA -- this should not be needed as C is caller save
+ Store C's SP
+ Restore ff's SP
+ POPA
+ ignoring the EFLAGS register, for now
+ not bothering with maintaining the values of the temporary registers
+*/
+#define PUSHALL \
+ PUSHQ R13; \
+ PUSHQ R12; \
+ PUSHQ R11; \
+ PUSHQ R10; \
+ PUSHQ R9; \
+ PUSHQ R8; \
+ PUSHQ BP; \
+ PUSHQ DI; \
+ PUSHQ SI; \
+ PUSHQ DX; \
+ PUSHQ CX; \
+ PUSHQ BX; \
+ PUSHQ AX;
+#define POPALL \
+ POPQ AX; \
+ POPQ BX; \
+ POPQ CX; \
+ POPQ DX; \
+ POPQ SI; \
+ POPQ DI; \
+ POPQ BP; \
+ POPQ R8; \
+ POPQ R9; \
+ POPQ R10; \
+ POPQ R11; \
+ POPQ R12; \
+ POPQ R13;
+#define PUSHREGS \
+ PUSHQ BP; \
+ PUSHQ DI; \
+ PUSHQ SI; \
+ PUSHQ AX;
+#define POPREGS \
+ POPQ AX; \
+ POPQ SI; \
+ POPQ DI; \
+ POPQ BP; \
+
+#define FF_TO_C_0 \
+ PUSHREGS; \
+ MOVQ SP, ffsp<>(SB); \
+ MOVQ csp<>(SB), SP; \
+ POPREGS;
+
+#define FF_TO_C_1 \
+ MOVQ AX, BX; \
+ POPQ AX; /* drop AX from the parameter stack */ \
+ FF_TO_C_0 \
+ MOVQ BX, BP; /* 1st argument in BP == RARG */
+
+/* ( 1st_parameter 2nd_parameter -- ) */
+#define FF_TO_C_2 /* for calling a c function with 2 parameters */ \
+ MOVQ AX, CX; \
+ POPQ AX; \
+ FF_TO_C_1 \
+ MOVQ CX, 8(SP) \
+
+/* ( 1st_parameter 2nd_parameter 3rd_parameter -- ) */
+#define FF_TO_C_3 /* for calling a c function with 3 parameters */ \
+ MOVQ AX, DX; \
+ POPQ AX; \
+ FF_TO_C_2 \
+ MOVQ DX, 16(SP) \
+
+/* no arguments when calling ff from C, for now */
+#define C_TO_FF \
+ PUSHREGS; \
+ MOVQ SP, csp<>(SB); \
+ MOVQ ffsp<>(SB), SP; \
+ POPREGS;
+
TEXT ffmain(SB), 1, $-4 /* _main(SB), 1, $-4 without the libc */
/* The last dictionary entry address is stored in dtop.
* The location of dtop is stored in the variable dp.
@@ -50,8 +154,13 @@
* (link + name(1+2) + code field address = 24 bytes) of the dp
* dictionary entry.
*/
- MOVQ $mventry_dp+24(SB), BX /* BX = dp parameter field address, which has the dtop address */
- MOVQ (BX), BX /* BX = *BX = dtop address */
+ PUSHREGS
+ MOVQ SP, csp<>(SB); /* store C stack pointer */
+ MOVQ $FFEND, SP /* setting up stack */
+ /*
+ * dtop address is stored in the parameter field address(24-32 bytes) of mventry_dp
+ */
+ MOVQ mventry_dp+24(SB), BX /* now, BX = dtop address */
MOVQ (BX), AX /* AX = *BX = $LAST = boot word address (defined last, stored at dtop) */
/* if 6a allows multiple symbols per address, then
the above 3 instructions would have been
@@ -69,7 +178,6 @@
* skipping over docol as we do not need to save the SI
* could have done LEAQ 24(AX), SI
*/
- MOVQ $FFEND, SP /* setting up stack, argc + argv */
/* lodsl could make this simpler. But, this is more comprehensible
why not JMP* (DI)?
@@ -81,6 +189,12 @@
NEXT
+TEXT ffprint(SB), 1, $-4
+ FF_TO_C_2
+ CALL screenput(SB)
+ C_TO_FF
+ NEXT
+
TEXT reset(SB), 1, $-4
MOVQ $FFSTART, BP
NEXT
@@ -95,6 +209,11 @@
LEAQ 8(DI), SI
NEXT
+TEXT exitcolon(SB), 1, $-4
+ SUBQ $8, BP
+ MOVQ (BP), SI
+ NEXT
+
TEXT dodoes(SB), 1, $-4 /* ( -- a ) */
MOVQ SI,(BP)
ADDQ $8,BP
@@ -124,7 +243,6 @@
MOVQ (AX), AX
NEXT
-/* shouldn't it be (a n -- )? */
TEXT store(SB), 1, $-4 /* ( n a -- ) */
POPQ (AX)
POPQ AX
@@ -346,11 +464,6 @@
ANDQ $~7, SI
NEXT
-TEXT exitcolon(SB), 1, $-4
- SUBQ $8, BP
- MOVQ (BP), SI
- NEXT
-
/* puts the top 2 entries of the data stack in the return stack */
TEXT doinit(SB), 1, $-4 /* ( hi lo -- ) */
MOVQ AX, (BP)
@@ -613,5 +726,8 @@
GLOBL htop(SB), $8
DATA heapend(SB)/8, $0
GLOBL heapend(SB), $8
+
+GLOBL ffsp<>(SB), $8
+GLOBL csp<>(SB), $8
END
--- a/os/pc64/main.c
+++ b/os/pc64/main.c
@@ -26,6 +26,9 @@
char bootdisk[KNAMELEN];
extern void ffmain(void); /* forth interpreter */
+extern intptr mventry_dp;
+extern intptr mc_dp;
+extern intptr dtop;
/* until I sort out the mp initialization issue */
extern void startaps(void);
@@ -82,7 +85,32 @@
nchars += msglen;
}
+/* used by ff */
void
+show_ff_return_stack(void)
+{
+ intptr* i;
+
+ for(i = (intptr*)0x112000; i<(intptr*)0x112020; i++){
+ print("0x%p: 0x%zx\n", i, *i);
+ }
+}
+
+void
+screenput(char *msg, int msglen)
+{
+ show_ff_return_stack();
+ print("msg %c, msglen %d\n", *msg, msglen);
+ if(screenputs != nil)
+ screenputs(msg, 1);
+ else
+ writemsg(msg, msglen);
+ print("\nscreenput exiting\n");
+ show_ff_return_stack();
+ print("\n");
+}
+
+void
ptedebug(uintptr pa, char *desc)
{
uintptr *pml4e, *pdpe, *pde;
@@ -113,7 +141,7 @@
"\tkdzero 0x%p confaddr 0x%p apbootstrap 0x%p idtaddr 0x%p\n"
"\tcpu0mach 0x%p cpu0sp 0x%p cpu0gdt 0x%p\n"
"\tcpu0pml4 0x%p cpu0pdp 0x%p cpu0pd 0x%p\n"
- "\tcpu0end 0x%p\n",
+ "\tcpu0end 0x%p\n"
"\tetext 0x%p edata 0x%p end 0x%p\n",
(void*)KDZERO, CONFADDR,APBOOTSTRAP,
IDTADDR, CPU0MACH, CPU0SP, GDTADDR,
@@ -252,7 +280,7 @@
init0(void)
{
Osenv *o;
- char buf[2*KNAMELEN];
+ /*char buf[2*KNAMELEN];*/
up->nerrlab = 0;
--- a/os/pc64/primitives-nasm.s
+++ b/os/pc64/primitives-nasm.s
@@ -63,3 +63,4 @@
MVENTRY "_end", textend, ffend, 4
MENTRY "cas", cas, 3
MENTRY "(deferred)", deferred, 10
+ MENTRY "ffprint", ffprint, 7
--- a/os/pc64/trap.c
+++ b/os/pc64/trap.c
@@ -253,7 +253,7 @@
print(" CS %4.4zux DS %4.4ux ES %4.4ux FS %4.4ux GS %4.4ux\n",
ureg->cs & 0xFFFF, ureg->ds & 0xFFFF, ureg->es & 0xFFFF,
ureg->fs & 0xFFFF, ureg->gs & 0xFFFF);
- print(" R8 %4.4zux R9 %4.4ux R10 %4.4ux R11 %4.4ux R12 %4.4ux\n",
+ print(" R8 %4.4zux R9 %4.4zzux R10 %4.4zux R11 %4.4zux R12 %4.4zux\n",
ureg->r8, ureg->r9, ureg->r10, ureg->r11, ureg->r12);
}
@@ -262,6 +262,7 @@
{
extern ulong etext;
vlong mca, mct;
+ intptr *i;
dumpregs2(ureg);
@@ -282,7 +283,15 @@
print("\n MCA %8.8zux MCT %8.8zux", mca, mct);
}
}
- print("\n ur %lux up %lux\n", ureg, up);
+ print("\n ur %lux up %lux ureg->bp & ~0xFFF %zx\n", ureg, up, ureg->bp & ~0xFFF);
+ if((ureg->bp & ~0xFFF) == FFSTART){
+ for(i = (intptr*)FFSTART; i<=(intptr*)ureg->bp; i++){
+ print("0x%p: 0x%zx\n", i, *i);
+ }
+ for(i = (intptr*)FFEND; i>=(intptr*)ureg->sp; i--){
+ print("0x%p: 0x%zx\n", i, *i);
+ }
+ }
}
/*
--- a/os/pc64/words-nasm.s
+++ b/os/pc64/words-nasm.s
@@ -264,6 +264,7 @@
VENTRY `stdin`, v_stdin, 5
VENTRY `stdout`, v_stdout, 6
VENTRY `eof`, v_eof, 3
+
CENTRY `key`, c_key, 3
dd v_iobuf ; variable iobuf
dd m_literal
@@ -285,23 +286,20 @@
dd m_cfetch
L79:
dd m_exitcolon
- CENTRY `emit`, c_emit, 4 ; ( character -- ) TODO correct the below stack notations
- dd v_iobuf ; variable iobuf
+
+ CENTRY `emit`, c_emit, 4 ; ( character -- )
+ dd v_iobuf ; variable iobuf address
dd m_cstore ; variable iobuf has character
- dd v_iobuf ; variable iobuf
+ dd v_iobuf ; variable iobuf address
dd m_literal
- dd 1 ; ( iobuf 1 -- )
- dd v_stdout ; variable stdout
- dd m_fetch ; ( iobuf 1 1 -- )
- dd m_fswrite ; ( -- ) writes out the character
- dd m_drop ; the return value of fswrite
+ dd 1 ; ( iobuf 1 -- )
+ dd m_ffprint ; calls c screenput()
dd m_exitcolon
+
CENTRY `type`, c_type, 4 ; ( addr n -- )
- dd v_stdout ; variable stdout, normally 1
- dd m_fetch ; ( addr n 1 -- )
- dd m_fswrite
- dd m_drop
+ dd m_ffprint
dd m_exitcolon
+
CENTRY `cr`, c_cr, 2
dd m_literal
dd 10 ; ascii value of carriage return
@@ -909,6 +907,7 @@
dd m_rpop
dd c_parse
dd m_exitcolon
+
CENTRY `accept`, c_accept, 6 ; ( a n -- ) TODO correct below stack notations
dd m_xswap ; ( n a -- )
dd m_dup ; ( n a a -- )
@@ -949,6 +948,7 @@
dd m_rpop ; ( a a -- )
dd m_minus ; ( 0 -- )
dd m_exitcolon
+
CENTRY `query`, c_query, 5
dd v_eof ; variable eof
dd c_off ; off sets variable eof = 0
@@ -974,6 +974,7 @@
dd c_off
L153:
dd m_exitcolon
+
CENTRY `refill`, c_refill, 6
dd v_blk
dd m_fetch
@@ -1699,6 +1700,7 @@
dd c_cr
dd c_abort
dd m_exitcolon
+
CENTRY `quit`, c_quit, 4 ; TODO correct below stack notations
dd m_reset ; initialize return stack
dd m_clear ; SP = sstack_end, initialize data stack
@@ -1720,6 +1722,7 @@
dd m_jump
dd L253
dd m_exitcolon
+
CENTRY `(abort)`, c_parenabort, 7 ; TODO correct below stack notations
dd v_state ; ( v_state -- )
dd c_off ; off sets variable state = 0
@@ -1736,6 +1739,7 @@
dd m_store ; variable stdout = 1
dd c_quit ; quit resets return stack and data stack
dd m_exitcolon
+
CENTRY `oldboot`, c_oldboot, 7 ; TODO correct below stack notations
dd m_reset
dd m_clear ; SP = sstack_end
--- a/os/port/proc.c
+++ b/os/port/proc.c
@@ -396,8 +396,8 @@
/* if(p->pid != prevpid){
prevpid = p->pid;
if(p->type == Interp && p->iprog != nil){
- print(" %d:%s,%d ",
- p->pid, p->text, ((Prog*)p->iprog)->pid);
+ print(" %d:%s,%d %s ",
+ p->pid, p->text, ((Prog*)p->iprog)->pid, ((Prog*)p->iprog)->R.M->m->path);
}else
print(" %d:%s", p->pid, p->text);
}else