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