\ Generischer Aufruf einer C-Funktion mit Adresse a-addr. \ \ Übergabe von x1..x4 als Argumente der Funktion (in Registern). Weitere \ Argumente i*x kann die Funktion vom Forth-Stack beziehen, allerdings muss \ man diese (und nur diese) in umgekehrter Reihenfolge auf den Stack legen, \ und am Ende selbst wieder vom Stack entfernen. \ \ Rückgabewerte der Funktion werden als x5 und x6 zurückgegeben. Je nachdem, \ ob und wieviel die Funktion zurückliefert, enthalten diese keine sinnreichen \ Werte. Z.B. liegen zurückgelieferte 'int' Werte nur in x5. ABI-CODE funcall ( i*x x1 x2 x3 x4 a-addr -- i*x x5 x6 ) 29 29 -12 addiu, \ Register 4, 31, 16 sichern 4 0 29 sw, 31 4 29 sw, 16 8 29 sw, \ Tausche Stackpointer von C-Stack und Forth-Stack \ Achtung Stackpointeroffset: Registerargumente in C reservieren auch \ (ungenutzten) Platz auf dem Stack! 16 29 move, \ C-Stackpointer in Register 16 sichern 29 4 4 addiu, \ Forth-Stackpointer zu C-Stackpointer 25 0 4 lw, \ a-addr laden 7 4 4 lw, \ Argumentregister 5-7 laden 6 8 4 lw, 5 12 4 lw, 31 25 jalr, \ Funktionsaufruf 4 16 4 lw, \ und Argument 4 laden (Sprungverzögerung beachten!) 29 16 move, \ C-Stackpointer wiederhestellen 4 0 29 lw, \ Register 4, 31, 16 wiederherstellen 31 4 29 lw, 16 8 29 lw, 29 29 12 addiu, 2 16 4 sw, \ Resultatregister 2, 3 auf Forth-Stack 3 12 4 sw, 31 jr, \ Funktions-Return 2 4 12 addiu, \ neuer Forth-Stackpointer in Reg. 2 zurück END-CODE \ Funktionsaufrufe von C-Funktionen mit bestimmter Zahl an \ Parametern/Rückgabewerten. Achtung: auch hier müssen ab dem 5. Argument \ alle Argumente in umgekehrter Reihenfolge übergeben werden! : void(void) >r 0 0 0 0 r> funcall 2drop ; : void(int) >r 0 0 0 r> funcall 2drop ; : void(2xint) >r 0 0 r> funcall 2drop ; : int(void) >r 0 0 0 0 r> funcall drop ; : int(int) >r 0 0 0 r> funcall drop ; : int(2xint) >r 0 0 r> funcall drop ; : int(3xint) >r 0 r> funcall drop ; : int(4xint) funcall drop ; : int(6xint) funcall drop nip nip ;