;;; -*-Midas-*-
;;;
-;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dosxcutl.asm,v 1.1 1992/05/05 06:55:13 jinx Exp $
+;;; $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/dosxcutl.asm,v 1.1.1.1 1992/07/28 14:28:15 jinx Exp $
;;;
;;; Copyright (c) 1992 Massachusetts Institute of Technology
;;;
;;;
.386
-.model small
+.model tiny
.code
\f
public _DPMI_GP_exception_method
mov ebx,28[ebp+28] ; trapped SS
mov edx,24[ebp+28] ; trapped ESP
cmp ecx,0
- jne set_up_trap_frame
+ jne DPMI_set_up_trap_frame
mov ecx,edx ; Use the trapped stack
mov eax,ebx ; to build the trap frame
\f
-set_up_trap_frame:
+DPMI_set_up_trap_frame:
push eax
pop es
push fs ; -8
push es ; -12
push ds ; -16
+
+;; The following code is shared by the exception handlers under DPMI
+;; and X32.
+
+ public common_exception_method_merge
+common_exception_method_merge:
push 36[ebp+4] ; -20 trapped ss
push 24[ebp+4] ; -24 trapped cs
push 28[ebp+4] ; -28 trapped eflags
mov edx,4[ebp+4] ; CS of handler
mov eax,0[ebp+4] ; EIP of handler
cmp edx,0 ; test CS of handler
- jne DPMI_use_far_call
+ jne common_use_far_call
call eax ; Invoke handler
- jmp DPMI_continue_after_exception
+ jmp common_continue_after_exception
-DPMI_after_continuation_setup:
+common_after_continuation_setup:
;; Build far RET frame on stack
push edx ; CS of handler
; ret far ; Invoke handler
db 0cbh
\f
-DPMI_use_far_call:
+common_use_far_call:
push cs ; Simulate a far call
- call DPMI_after_continuation_setup
+ call common_after_continuation_setup
-DPMI_continue_after_exception:
+common_continue_after_exception:
;;
;; If the handler returns, update machine state and `return' to
;; the trapped code.
push eax ; -4
mov ax,ss
cmp ax,36[ebp+4]
- jne DPMI_different_stacks
+ jne common_different_stacks
lea eax,40[ebp+4]
cmp eax,32[ebp+4]
- jne DPMI_different_stacks
+ jne common_different_stacks
;; Easy case: The target stack is what we would return to trivially.
;; Overwrite SS and ESP with CS and EIP, restore flags, and do a far
; ret far ; resume thread
db 0cbh
-DPMI_different_stacks:
+common_different_stacks:
push edx ; -8 Scratch regs
push ds ; -12 These two must be contiguous
push ecx ; -16 for LDS instruction below!
; ret far ; resume thread
db 0cbh
+\f
+;; Locked data for X32.
+;; It includes all the data and code accessed during a hardware
+;; interrupt or an exception before X32 is reset, i.e. while
+;; it cannot process a page fault.
+
+ .data
+ public _X32_locked_data_start
+_X32_locked_data_start dd 0
+
+X32_excp_buffer db 64 dup(0)
+ public _X32_excp_handlers
+_X32_excp_handlers db 32*20 dup (0)
+
+ public _X32_ds_val
+_X32_ds_val dd 06765h
+ public _X32_timer_interrupt_previous
+_X32_timer_interrupt_previous dd 0
+ dd 0
+ dd 0
+
+ public _scm_itimer_counter
+_scm_itimer_counter dd 0
+ public _scm_itimer_reload
+_scm_itimer_reload dd 0
+
+ public _IntCode
+_IntCode dd 0
+ public _IntEnb
+_IntEnb dd 0
+ public _MemTop
+_MemTop dd 0
+
+ public _Regstart
+_Regstart db 128 dup (0)
+ public _Registers
+_Registers dd 0
+
+ public _X32_locked_data_end
+_X32_locked_data_end db 3452 dup (0)
+ .code
+\f
+;; Exception handlers for X32 and X32V.
+;; This code is not reentrant.
+;; The same exception within this code will really confused the world.
+;; It should be rewritten in the future to be reentrant.
+
+;; frame on entry to _X32_exception_method (sp points to 0)
+;;
+;; 12 pointer to interrupt structure
+;; 8 eflags at interrupt
+;; 4 CS for IRETD
+;; 0 EIP for IRETD
+;; -4 old DS
+;; -8 old EAX
+;; -12 old ECX
+;; -16 old EDX
+
+X32FRAME equ 16
+
+;; The pointer to the interrupt structure points to offset 0 of
+;; a block on SS whose layout is
+
+;; 32 dword SS
+;; 28 dword ESP
+;; 24 dword EFLAGS
+;; 20 dword CS
+;; 16 dword EIP
+;; 14 mode 0 for int. in real mode, 1 for int. in prot. mode, 2 for excp.
+;; 12 INT# 0 - 256
+;; 10 word GS
+;; 8 word FS
+;; 6 word ES
+;; 4 word DS
+;; 0 dword EAX
+;; -4 trap error code
+
+ public _X32_locked_code_start
+_X32_locked_code_start:
+
+ public _X32_exception_method
+_X32_exception_method:
+ push ds ; Preserve registers
+ push eax
+ push ecx
+ push edx
+
+ mov ecx,12[esp+X32FRAME] ; Pointer to structure
+ mov ds,_X32_ds_val ; Temporary buffer
+
+ mov ax,2501h ; Restore X32's internal state
+ int 21h
+ mov ax,4c00h ;terminate program
+ int 21h
+
+ lea edx,X32_excp_buffer
+
+ xor eax,eax
+ mov ax,ss:32[ecx] ; SS at time of trap
+ mov 0[edx],eax
+
+ mov eax,ss:28[ecx] ; ESP at time of trap
+ mov 4[edx],eax
+
+ mov eax,ss:24[ecx] ; EFLAGS at time of trap
+ mov 8[edx],eax
+
+ xor eax,eax
+ mov ax,ss:20[ecx] ; CS at time of trap
+ mov 12[edx],eax
+
+ mov eax,ss:16[ecx] ; EIP at time of trap
+ mov 16[edx],eax
+
+ mov eax,ss:-4[ecx] ; Trap code
+ mov 20[edx],eax
+
+ xor eax,eax ; Trapped gs
+ mov ax,ss:10[ecx]
+ mov 24[edx],eax
+
+ xor eax,eax ; Trapped fs
+ mov ax,ss:8[ecx]
+ mov 28[edx],eax
+
+ xor eax,eax ; Trapped es
+ mov ax,ss:6[ecx]
+ mov 32[edx],eax
+
+ xor eax,eax ; Trapped ds
+ mov ax,ss:4[ecx]
+ mov 36[edx],eax
+
+ mov eax,ss:[ecx] ; Trapped eax
+ mov 40[edx],eax
+
+ mov eax,[esp] ; Trapped edx
+ mov 44[edx],eax
+
+ mov eax,4[esp] ; Trapped ecx
+ mov 48[edx],eax
+
+ xor eax,eax
+ mov ax,ss:12[ecx] ; Trap number
+ mov 52[edx],eax
+
+ mov ecx,eax ; Multiply by 20
+ shl eax,2
+ add eax,ecx
+ shl eax,2
+
+ lea ecx,dword ptr _X32_excp_handlers
+ add ecx,eax ; handler info for this excp.
+
+ mov eax,cs:[ecx] ; handler ESP
+ cmp eax,0 ; Use trapped stack?
+ jne X32_set_up_trap_sp
+
+ lss esp,fword ptr [edx] ; Restore trapped stack
+ jmp X32_set_up_trap_sp_merge
+
+X32_set_up_trap_sp:
+ lss esp,fword ptr cs:[ecx] ; Use stack specified by handler
+
+X32_set_up_trap_sp_merge:
+
+ mov ax,2501h ; Restore X32's internal state
+ int 21h
+ jmp X32_set_up_trap_stack
+
+;; Note: X32_set_up_stack does not need to be locked in memory
+;; because we get to it after resetting X32 (i.e. scheme is
+;; executing as a normal program again), so it should be able to
+;; page it in if necessary.
+\f
+;; X32 timer interrupt.
+;; Must be locked in memory (and all the data it accesses.
+
+INT_Timer equ 64
+REGBLOCK_MEMTOP equ 0
+
+ public _X32_timer_interrupt
+_X32_timer_interrupt:
+ push ds
+ mov ds,cs:_X32_ds_val
+ cmp dword ptr _scm_itimer_reload,0
+ je x32_timer_return
+ dec dword ptr _scm_itimer_counter
+ cmp dword ptr _scm_itimer_counter,0
+ jne x32_timer_return
+ push eax
+ mov eax,dword ptr _scm_itimer_reload
+ mov dword ptr _scm_itimer_counter,eax
+ or _IntCode,INT_Timer
+ mov eax,_IntCode
+ and eax,_IntEnb
+ cmp eax,0
+ je x32_timer_continue
+ mov dword ptr _Registers[REGBLOCK_MEMTOP],-1
+
+x32_timer_continue:
+ pop eax
+
+x32_timer_return:
+ pop ds
+ jmp fword ptr cs:_X32_timer_interrupt_previous
+
+ public _X32_locked_code_end
+_X32_locked_code_end:
+
+
+X32_set_up_trap_stack:
+ push 0[edx] ; Trapped SS
+ push 4[edx] ; Trapped ESP
+ push 8[edx] ; Trapped EFLAGS
+ push 12[edx] ; Trapped CS
+ push 16[edx] ; Trapped EIP
+ push 20[edx] ; Trap code
+ push 52[edx] ; Trap number
+ push 16[ecx] ; C handler DS
+ push 12[ecx] ; C handler CS
+ push 8[ecx] ; C handler EIP
+ push ebp ; Trapped EBP
+ mov ebp,esp
+ push 24[edx] ; Trapped GS
+ push 28[edx] ; Trapped FS
+ push 32[edx] ; Trapped ES
+ push 36[edx] ; Trapped DS
+ mov eax,40[edx] ; Restore trapped EAX
+ mov ecx,48[edx] ; Restore trapped ECX
+ mov edx,44[edx] ; Restore trapped EDX
+ jmp common_exception_method_merge
+
+ public _X32_asm_initialize
+_X32_asm_initialize:
+ mov _X32_ds_val,ds
+ ret
end