1;
2;  Title:  Assembly code routines for the poly system.
3;  Author:    David Matthews
4;  Copyright (c) David C. J. Matthews 2000-2020
5;
6;  This library is free software; you can redistribute it and/or
7;  modify it under the terms of the GNU Lesser General Public
8;  License version 2.1 as published by the Free Software Foundation.
9;
10;  This library is distributed in the hope that it will be useful,
11;  but WITHOUT ANY WARRANTY; without even the implied warranty of
12;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13;  Lesser General Public License for more details.
14;
15;  You should have received a copy of the GNU Lesser General Public
16;  License along with this library; if not, write to the Free Software
17;  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18;
19
20;
21; Registers used :-
22;
23;  eax: First argument to function.  Result of function call.
24;  ebx: Second argument to function.
25;  ecx: General register
26;  edx: Closure pointer in call.
27;  ebp: Points to memory used for extra registers
28;  esi: General register.
29;  edi: General register.
30;  esp: Stack pointer.
31
32.486
33    .model  flat,c
34
35Fr_Size             EQU     16		; Make this a multiple of 16
36
37; This is the argument vector passed in to X86AsmSwitchToPoly
38; It is used to initialise the frame.  A few values are updated
39; when ML returns.
40ArgVector STRUCT
41LocalMPointer       DWORD   ?
42HandlerRegister     DWORD   ?
43LocalMbottom        DWORD   ?
44StackLimit          DWORD   ?
45ExceptionPacket     DWORD   ?       ; Address of packet to raise
46UnusedRequestCode   DB      ?       ; Byte: Io function to call.
47UnusedFlag          DB      ?
48ReturnReason        DB      ?       ; Byte: Reason for returning from ML.
49UnusedRestore       DB      ?       ;
50SaveCStack          DWORD   ?       ; Saved C stack pointer
51ThreadId            DWORD   ?       ; My thread id
52StackPtr            DWORD   ?       ; Stack pointer
53UnusedProgramCtr    DWORD   ?
54HeapOverFlowCall    DWORD   ?
55StackOverFlowCall   DWORD   ?
56StackOverFlowCallEx DWORD   ?
57TrapHandlerEntry    DWORD   ?
58SaveRAX             DWORD   ?
59SaveRBX             DWORD   ?
60SaveRCX             DWORD   ?
61SaveRDX             DWORD   ?
62SaveRSI             DWORD   ?
63SaveRDI             DWORD   ?
64SaveFP              WORD   ?         ; Actually larger
65ArgVector ENDS
66
67
68; Codes to indicate the reason for return.
69RETURN_HEAP_OVERFLOW        EQU 1
70RETURN_STACK_OVERFLOW       EQU 2
71RETURN_STACK_OVERFLOWEX     EQU 3
72RETURN_CALLBACK_RETURN      EQU 6
73RETURN_CALLBACK_EXCEPTION   EQU 7
74RETURN_KILL_SELF            EQU 9
75
76;
77; CODE STARTS HERE
78;
79    .CODE
80
81; Enter ML code.  This is now only ever used to start a new thread.
82; It is probably unnecessary to save the callee-save regs or load the ML regs.
83PUBLIC  X86AsmSwitchToPoly
84X86AsmSwitchToPoly:
85    push    ebp                             ; Standard entry sequence
86    mov     ebp,[8+esp]                     ; Address of argument vector
87    push    ebx                             ; Push callee-save registers
88    push    edi
89    push    esi
90    sub     esp,(Fr_size-12)                ; Allocate frame
91    mov     [ArgVector.SaveCStack+ebp],esp
92	mov     esp,[ArgVector.StackPtr+ebp]
93    frstor  [ArgVector.SaveFP+ebp]
94    mov     eax,[ArgVector.SaveRAX+ebp]
95    mov     ebx,[ArgVector.SaveRBX+ebp]
96    mov     ecx,[ArgVector.SaveRCX+ebp]
97    mov     edx,[ArgVector.SaveRDX+ebp]
98    mov     esi,[ArgVector.SaveRSI+ebp]
99    mov     edi,[ArgVector.SaveRDI+ebp]
100    cld                                     ; Clear this just in case
101    jmp     dword ptr [edx]
102
103; Save all the registers and enter the trap handler.
104; It is probably unnecessary to save the FP state now.
105X86TrapHandler PROTO C
106
107CallTrapHandler:
108    mov     [ArgVector.SaveRAX+ebp],eax
109    mov     [ArgVector.SaveRBX+ebp],ebx
110    mov     [ArgVector.SaveRCX+ebp],ecx
111    mov     [ArgVector.SaveRDX+ebp],edx
112    mov     [ArgVector.SaveRSI+ebp],esi
113    mov     [ArgVector.SaveRDI+ebp],edi
114    FNSAVE  [ArgVector.SaveFP+ebp]          ; Save FP state.  Also resets the state so...
115    FLDCW   [ArgVector.SaveFP+ebp]          ; ...load because we need the same rounding mode in the RTS
116    mov     [ArgVector.StackPtr+ebp],esp    ; Save ML stack pointer
117    mov     esp,[ArgVector.SaveCStack+ebp]  ; Restore C stack pointer
118    sub     esp,12                          ; Align stack ptr - GCC prefers this
119    push    [ArgVector.ThreadId+ebp]
120
121    call    [ArgVector.TrapHandlerEntry+ebp]
122    add     esp,16
123	mov     esp,[ArgVector.StackPtr+ebp]
124    mov     eax,[ArgVector.ExceptionPacket+ebp]
125    cmp     eax,1                                           ; Did we raise an exception?
126    jnz     raisexcept
127    frstor  [ArgVector.SaveFP+ebp]
128    mov     eax,[ArgVector.SaveRAX+ebp]
129    mov     ebx,[ArgVector.SaveRBX+ebp]
130    mov     ecx,[ArgVector.SaveRCX+ebp]
131    mov     edx,[ArgVector.SaveRDX+ebp]
132    mov     esi,[ArgVector.SaveRSI+ebp]
133    mov     edi,[ArgVector.SaveRDI+ebp]
134    cld                                     ; Clear this just in case
135    ret
136raisexcept:
137    mov     ecx,[ArgVector.HandlerRegister+ebp]
138    jmp     dword ptr [ecx]
139
140; Define standard call macro.
141; Defined as an Masm macro because there are multiple instructions.
142
143CALL_EXTRA  MACRO   index
144    mov     byte ptr [ArgVector.ReturnReason+ebp],index
145    jmp     CallTrapHandler
146ENDM
147
148; This implements atomic addition in the same way as atomic_increment
149; N.B. It is called from the RTS so uses C linkage conventions.
150PUBLIC  X86AsmAtomicDecrement
151X86AsmAtomicDecrement:
152    mov     eax,4[esp]
153; Use ecx and eax because they are volatile (unlike ebx on X86/64/Unix)
154    mov     ecx,-2
155    lock xadd [eax],ecx
156    sub     ecx,2
157    mov     eax,ecx
158    ret
159
160CREATE_EXTRA_CALL MACRO index
161PUBLIC  X86AsmCallExtra&index&
162X86AsmCallExtra&index&:
163    CALL_EXTRA index
164    ENDM
165
166
167CREATE_EXTRA_CALL RETURN_HEAP_OVERFLOW
168CREATE_EXTRA_CALL RETURN_STACK_OVERFLOW
169CREATE_EXTRA_CALL RETURN_STACK_OVERFLOWEX
170
171END
172