Page 58,132 Title INT.ASM Interrupt Processor ;****************************************************************************** ; ; Name: INT.ASM Interrupt Processor ; ; Group: Emulator ; ; Revision: 1.00 ; ; Date: January 30, 1988 ; ; Author: Randy W. Spurlock ; ;****************************************************************************** ; ; Module Functional Description: ; ; This module contains all the code for the Apple ; emulator interrupt handler. ; ;****************************************************************************** ; ; Changes: ; ; DATE REVISION DESCRIPTION ; -------- -------- ------------------------------------------------------- ; 1/30/88 1.00 Original ; ;****************************************************************************** Page ; ; Public Declarations ; Public Int_Init ; Interrupt initialization routine Public Int_Reset ; Interrupt reset routine ; Public Int_Update ; Emulator interrupt update routine ; Public Int_Process ; Interrupt processing routine Public Dummy_Int ; Dummy interrupt processing routine ; ; External Declarations ; ; Extrn Timer_Int:Near ; Timer interrupt routine (TIMER) ; Extrn Timer_Init:Near ; Timer initialization routine (TIMER) ; Extrn Timer_Reset:Near ; Timer reset routine (TIMER) Extrn Key_Int:Near ; Keyboard interrupt routine (KEYBOARD) Extrn Emulator:Near ; Emulator entry point (EMULATE) Extrn Error:Near ; Apple emulator error routine (APPLE) Extrn Exit:Near ; Apple emulator exit routine (APPLE) ; Extrn Int_Table:Word ; Interrupt jump table (DATA) Extrn Original_Int_3:Dword ; Original interrupt 3 vector (DATA) Extrn Original_Int_8:Dword ; Original interrupt 8 vector (DATA) Extrn Original_Int_9:Dword ; Original interrupt 9 vector (DATA) Extrn System_Flag:Byte ; Apple emulator system flag byte(DATA) Extrn Emulate_Flag:Byte ; Emulator interrupt flag byte (DATA) ; ; LOCAL Equates ; MAX_INTERRUPT Equ 08h ; Maximum interrupt count value ;INT_DEBUG Equ 03h ; Processor debug interrupt number ;INT_TIMER Equ 08h ; Timer hardware interrupt number INT_KEY Equ 09h ; Keyboard hardware interrupt number ;STACK_CLEAR Equ 06h ; Number of bytes needed to clear stack NEXT_OFFSET Equ 02h ; Next interrupt table entry offset INT_MASK Equ 0FEh ; Dummy interrupt clear mask value ; ; Define any include files needed ; Include Macros.inc ; Include the macro definitions Include Equates.inc ; Include the equate definitions Include Strucs.inc ; Include the structure definitions .286c ; Include 80286 instructions Page ; ; Define the emulator code segment ; Emulate Segment Word Public 'EMULATE' ; Emulator code segment Assume cs:Emulate, ds:Nothing, es:Nothing Subttl Int_Init Interrupt Initialization Page + ;****************************************************************************** ; ; Int_Init() ; ; Save the required registers ; Save the original interrupt 3 (Debug) vector ; Save the original interrupt 8 (Timer) vector ; Save the original interrupt 9 (Keyboard) vector ; Set the new interrupt 3 vector ; Set the new interrupt 8 vector ; Call the timer initialization routine ; Set the new interrupt 9 vector ; Set the interrupt patched flag ; Restore the required registers ; Return to the caller ; ; Registers on Entry: ; ; None ; ; Registers on Exit: ; ; None ; ;****************************************************************************** Even ; Force procedure to even address Int_Init Proc Near ; Interrupt initialization procedure Save ax,bx,dx,ds,es ; Save the required registers ; mov ah,GET_VECTOR ; Get interrupt vector function code ; mov al,INT_DEBUG ; Get processor debug interrupt (3) ; int DOS ; Get the current debug interrupt ; mov Word Ptr cs:[Original_Int_3 + 0],bx ; mov Word Ptr cs:[Original_Int_3 + 2],es ; mov ah,GET_VECTOR ; Get interrupt vector function code ; mov al,INT_TIMER ; Get timer hardware interrupt (8) ; int DOS ; Get the current timer interrupt ; mov Word Ptr cs:[Original_Int_8 + 0],bx ; mov Word Ptr cs:[Original_Int_8 + 2],es mov ah,GET_VECTOR ; Get interrupt vector function code mov al,INT_KEY ; Get keyboard hardware interrupt (9) int DOS ; Get the current keyboard interrupt mov Word Ptr cs:[Original_Int_9 + 0],bx mov Word Ptr cs:[Original_Int_9 + 2],es mov ax,cs ; Get the current CS register value mov ds,ax ; Setup DS to current CS value ; lea dx,cs:[Int_Process] ; Get the interrupt processing offset ; mov ah,SET_VECTOR ; Get set interrupt vector function code ; mov al,INT_DEBUG ; Get processor debug interrupt (3) ; int DOS ; Set the new debug interrupt ; lea dx,cs:[Timer_Int] ; Get the new timer interrupt offset ; mov ah,SET_VECTOR ; Get set interrupt vector function code ; mov al,INT_TIMER ; Get timer hardware interrupt (8) ; int DOS ; Set the new timer interrupt ; call Timer_Init ; Call the timer initialization routine lea dx,cs:[Key_Int] ; Get the new keyboard interrupt offset mov ah,SET_VECTOR ; Get set interrupt vector function code mov al,INT_KEY ; Get keyboard hardware interrupt (9) int DOS ; Set the new keyboard interrupt or cs:[System_Flag],PATCHED; Set interrupts patched flag Restore ax,bx,dx,ds,es ; Restore the required registers ret ; Return to the caller Int_Init Endp ; End of the Int_Init procedure Subttl Int_Reset Interrupt Reset Page + ;****************************************************************************** ; ; Int_Reset() ; ; Save the required registers ; If interrupts have been patched ; Call the timer reset routine ; Restore the original interrupt 3 (Debug) vector ; Restore the original interrupt 8 (Timer) vector ; Restore the original interrupt 9 (Keyboard) vector ; Endif interrupts not patched ; Restore the required registers ; Return to the caller ; ; Registers on Entry: ; ; None ; ; Registers on Exit: ; ; None ; ;****************************************************************************** Even ; Force procedure to even address Int_Reset Proc Near ; Interrupt reset procedure Save ax,dx,ds ; Save the required registers test cs:[System_Flag],PATCHED; Check for interrupts patched jz Reset_Done ; Jump if interrupts not patched ; call Timer_Reset ; Call the timer reset routine ; mov ah,SET_VECTOR ; Get the set interrupt function code ; mov al,INT_DEBUG ; Get processor debug interrupt (3) ; mov dx,Word Ptr cs:[Original_Int_3 + 0] ; mov ds,Word Ptr cs:[Original_Int_3 + 2] ; int DOS ; Restore original debug interrupt ; mov ah,SET_VECTOR ; Get the set interrupt function code ; mov al,INT_TIMER ; Get timer hardware interrupt (8) ; mov dx,Word Ptr cs:[Original_Int_8 + 0] ; mov ds,Word Ptr cs:[Original_Int_8 + 2] ; int DOS ; Restore original timer interrupt mov ah,SET_VECTOR ; Get the set interrupt function code mov al,INT_KEY ; Get keyboard hardware interrupt (9) mov dx,Word Ptr cs:[Original_Int_9 + 0] mov ds,Word Ptr cs:[Original_Int_9 + 2] int DOS ; Restore original keyboard interrupt Reset_Done: Restore ax,dx,ds ; Restore the required registers ret ; Return to the caller Int_Reset Endp ; End of the Int_Reset procedure Subttl Int_Update Emulator Interrupt Update Routine Page + ;****************************************************************************** ; ; Int_Update(RAM_Space, Registers, Address, Stack_Frame) ; ; Save the required registers ; If currently executing 65C02 emulator ; If there is a pending interrupt request ; Set the emulator interrupt flag bit ; Endif ; Endif ; Restore the required registers ; Return control to the caller ; ; Registers on Entry: ; ; DL - 65C02 Accumulator ; DH - 65C02 processor flags ; CL - 65C02 Y index register ; CH - 65C02 X index register ; BX - 65C02 Stack pointer ; SI - 65C02 Program counter ; DI - Current opcode address ; DS - 65C02 RAM space ; SS:SP - Stack Frame ; ; Registers on Exit: ; ; AX - Destroyed ; DH - Emulator interrupt set if interrupt pending ; ;****************************************************************************** ; Even ; Force procedure to even address ;Int_Update Proc Near ; Emulator interrupt update procedure ; Save bp ; Save the required registers ; mov bp,sp ; Setup access to the stack frame ; mov ax,cs ; Get the Emulate code segment value ; cmp ax,ss:[bp.Current_CS] ; Check for executing in Emulate segment ; jne Update_Exit ; Jump if NOT in the Emulate segment ; lea ax,cs:[Emulator] ; Get emulator entry point address ; cmp ax,ss:[bp.Current_IP] ; Check for executing 65C02 emulator ; jbe Update_Exit ; Jump if NOT in 65C02 emulator ; test cs:[Emulate_Flag],INT_REQUEST ; jz Update_Exit ; Jump if no pending interrupt ; or dh,CPU_R ; Set emulator interrupt flag bit ;Update_Exit: ; Restore bp ; Restore the required registers ; ret ; Return control to the caller ;Int_Update Endp ; End of the Interrupt procedure ; Subttl Interrupt Interrupt Processor ; Page + ;****************************************************************************** ; ; Int_Process(RAM_Space, Registers, Address) ; ; Clear the stack frame (Dump return address and flags) ; Enable interrupts once again ; Clear the emulator interrupt flag bit ; Setup Interrupt_Counter (MAX_INTERRUPT - 1 = 7) ; While Interrupt_Counter >= 0 ; If this interrupt bit is set ; Jump to the correct routine for interrupt ; Endif ; Decrement the Interrupt_Counter ; Endwhile ; Go process the next opcode ; ; Registers on Entry: ; ; DL - 65C02 Accumulator ; DH - 65C02 processor flags ; CL - 65C02 Y index register ; CH - 65C02 X index register ; BX - 65C02 Stack pointer ; SI - 65C02 Program counter ; DI - Current opcode address ; DS - 65C02 RAM space ; ; Registers on Exit: ; ; AX - Destroyed ; BP - Destroyed ; ;****************************************************************************** ; Even ; Force procedure to even address ;Int_Process Proc Near ; Interrupt processing procedure ; add sp,STACK_CLEAR ; Clear stack frame (Address/Flags) ; sti ; Enable interrupts once again ; and dh,Not CPU_R ; Clear emulator interrupt flag bit ; xor ah,ah ; Initialize the interrupt counter ; mov al,cs:[Emulate_Flag] ; Get the emulator flags (Interrupt) ; xor bp,bp ; Initialize interrupt table offset ;Interrupt_Loop: ; shr al,1 ; Check for interrupt occurred ; jnc Next_Interrupt ; Jump if this is not the interrupt ; call cs:[bp + Int_Table] ; Call routine to handle the interrupt ; or al,al ; Check for more interrupts to process ; jz Interrupt_Exit ; Jump if all interrupts handled ;Next_Interrupt: ; add bp,NEXT_OFFSET ; Increment to next interrupt offset ; inc ah ; Increment the interrupt counter ; cmp ah,MAX_INTERRUPT ; Check against maximum interrupt ; jb Interrupt_Loop ; Jump if more interrupts to check ;Interrupt_Exit: ; jmp di ; Go process the next opcode ;Int_Process Endp ; End of the Int_Process procedure ; Subttl Dummy_Int Dummy Interrupt Routine ; Page + ;****************************************************************************** ; ; Dummy_Int(Interrupt_Number, Pending, RAM_Space, Registers, Address) ; ; Save the required registers ; Calculate interrupt mask value ; Clear the pending dummy interrupt ; Restore the required registers ; Return control to the caller ; ; Registers on Entry: ; ; AH - Interrupt number ; AL - Pending interrupt flags ; DL - 65C02 Accumulator ; DH - 65C02 processor flags ; CL - 65C02 Y index register ; CH - 65C02 X index register ; BX - 65C02 Stack pointer ; SI - 65C02 Program counter ; DI - Current opcode address ; DS - 65C02 RAM space ; ; Registers on Exit: ; ; None ; ;****************************************************************************** Even ; Force procedure to even address Dummy_Int Proc Near ; Interrupt processing procedure Save ax,cx ; Save the required registers mov ah,INT_MASK ; Get interrupt mask value mov cl,al ; Get the interrupt number in CL rol ah,cl ; Rotate interrupt mask into position and cs:[Emulate_Flag],ah ; Clear the current dummy interrupt Restore ax,cx ; Restore the required registers ret ; Return control to the caller Dummy_Int Endp ; End of the Dummy_Int procedure ;****************************************************************************** ; ; Define the end of the Emulator Code Segment ; ;****************************************************************************** Emulate Ends End ; End of the Int module