-
Notifications
You must be signed in to change notification settings - Fork 0
/
exception.c
executable file
·271 lines (260 loc) · 7.15 KB
/
exception.c
1
#include <types.h>#include <quickdraw.h>#define _EXCEPTION_C#include "exception.h"#include "aprintf.h"#include "arithmetic_fault.h"#include "clock.h"#include "iow.h"#include "mmemory.h"#include "docmds.h" #include "macdev.h" #include "execute.h" #include "func.h"#pragma segment EXCEPTIONSvoid reserved_or_priviledged( char *cause){ exception(FAULT,V_RoPI,cause,0,0);}void memory_fault( address v, char *cause, address a, unsigned long details){ if(exceptions_on) /*am reporting problems and haven't stopped*/ { if(a == SP && CMD == 0) { if(IS) { aprintf("Interrupt Stack SP invalid"); stop = 1; return; } else { exception(ABORT,V_KSPNV,cause,2,a,details); return; } } exception(FAULT,v,cause,2,a,details); }}void exception( long what, /*abort , fault, trap*/ address fault_vector_offset, char *cause, unsigned long nargs, unsigned long args, /***********HACK depends on arg order***************/ ...){vector new_pc;unsigned long old_psl;unsigned long *u = & args; /***********HACK depends on arg order***************/long i; if(exceptions_on == 0 || fault_vector_offset == V_PR) return; /*ignore request*/ if(what == FAULT) { exceptions_on = 0; /*Stop further faults*/ fix_registers(); exceptions_on = 1; /*allow further faults*/ TP = 0; } old_psl = PSL; new_pc.vector_as_long = (address) vax_fetchliR(IPR(SCBB) + fault_vector_offset); if(SERVICED_ON(new_pc) != 1 && SERVICED_ON(new_pc) != 0) { aprintf("Invalid vector (%s) 0x%X: 0x%X",cause,virtual(IPR(SCBB) + fault_vector_offset), new_pc.vector_as_long); stop = 1; stop_writes = 1; exceptions_on = 0; /*Stop further faults for this instruction*/ return; } if(fault_vector_offset == V_MCV || fault_vector_offset == V_KSPNV) { /*deep shit faults*/ IPL = 0x1F; if( SERVICED_ON(new_pc) != 1) { if(fault_vector_offset == V_MCV) { aprintf("Vector for \"Machine Check\" 0x%X: 0x%X\nmust have the low 2 bits set to 01",virtual(IPR(SCBB) + fault_vector_offset),new_pc.vector_as_long); } else { aprintf("Vector for \"Kernel Stack Not Valid\" 0x%X: 0x%X\nmust have the low 2 bits set to 01\n",virtual(IPR(SCBB) + fault_vector_offset),new_pc.vector_as_long); } stop = 1; stop_writes = 1; exceptions_on = 0; /*Stop further faults for this instruction*/ return; } } if(!IS) { IPR(CMD) = SP; IPR(CMD+KFP) = FP; /*Hack for stackw*/ if( SERVICED_ON(new_pc) == 0) SP = IPR(KSP); else { SP = IPR(ISP); IS = 1; } } PMD = CMD; CMD = KSP; SP -= 4; vax_putl( old_psl, SP ); SP -= 4; if(what == TRAP) vax_putl( PC, SP ); else vax_putl( old_pc, SP ); for(i = 0;i < nargs; i++) { SP -= 4; vax_putl( *u++, SP );/***********HACK depends on arg order***************/ } PC = HANDLER_ADDRESS(new_pc); CM = TP = FPD = DV = FU = IV = T = N = Z = V = C = 0; if(PC == 0) { aprintf("Fault (%s)\nHalted No Vector (0x%X: 0x%X) defined",cause,virtual(IPR(SCBB) + fault_vector_offset),new_pc.vector_as_long); for(i = 0;i < nargs; i++) SP += 4; rei("rei"); stop = 1; } exceptions_on = 0; /*Stop further faults for this instruction*/ stop_writes = 1;}void service_interrupt(void) {unsigned long interrupts = IPR(SISR) & ~(( 1 << (IPL + 1)) - 1 );unsigned long i;long j;vector new_pc;unsigned long old_psl;long new_ipl;address interrupt_vector_offset; if(interrupts ) { /*then there is an interrupt pending*/ if( interrupts & HI_WORD_MASK ) { /*hardware interrupt. Do in order of priority*/ if(interrupts & ICR_INTERRUPT_BIT) { IPR(SISR) &= ~ICR_INTERRUPT_BIT; /*clear the interrupt bit*/ if((interrupt_vector_offset = clock_interrupt()) == 0) return; /*interrupt bit has been cleared in the clock status register*/ new_pc.vector_as_long = (address)vax_fetchliR(IPR(SCBB) + interrupt_vector_offset); new_ipl = ICR_INTERRUPT_LEVEL; } else if(interrupts & MACVAX_INTERRUPT_BIT) { IPR(SISR) &= ~MACVAX_INTERRUPT_BIT; /*clear the interrupt bit*/ if((interrupt_vector_offset = macvax_interrupt()) == 0) return; /*interrupt bit has been cleared in the macvax command status register*/ new_pc.vector_as_long = (address)vax_fetchliR(IPR(SCBB) + interrupt_vector_offset); new_ipl = MACVAX_INTERRUPT_LEVEL; } else if(interrupts & CONSOLE_INTERRUPT_BIT) { IPR(SISR) &= ~CONSOLE_INTERRUPT_BIT; /*clear the interrupt bit*/ if((interrupt_vector_offset = console_interrupt()) == 0) return; /*interrupt cancelled*/ new_pc.vector_as_long = (address)vax_fetchliR(IPR(SCBB) + interrupt_vector_offset); new_ipl = CONSOLE_INTERRUPT_LEVEL; } else { /*don't know what is interrupting*/ aprintf("Spurious Interrupt"); stop = 1; return; } } else { /*software interrupt*/ /*find the highest interrupt pending*/ for( i = WORD_HI_BIT, j = 0xF; (i & interrupts) == 0; i >>= 1, j--) /*no body*/ ; IPR(SISR) &= ~i; /*clear interrupt bit*/ interrupt_vector_offset = V_SWI1 + ((j - 1) << 2 ) ; new_pc.vector_as_long = (address)vax_fetchliR( IPR(SCBB) + interrupt_vector_offset ); new_ipl = j; } if(FPD) TP = 0; old_psl = PSL; if(SERVICED_ON(new_pc) != 1 && SERVICED_ON(new_pc) != 0) { aprintf("Invalid interrupt vector %X: %X",virtual(IPR(SCBB) + interrupt_vector_offset),new_pc.vector_as_long); stop = 1; return; } if(interrupt_vector_offset == V_MCV || interrupt_vector_offset == V_KSPNV) { /*deep shit faults*/ new_ipl = 0x1F; if( SERVICED_ON(new_pc) != 1) { if(interrupt_vector_offset == V_MCV) { aprintf("Vector for \"Machine Check\" 0x%X: 0x%X\nmust have the low 2 bits set to 01",virtual(IPR(SCBB) + interrupt_vector_offset),new_pc.vector_as_long); } else { aprintf("Vector for \"Kernel Stack Not Valid\" 0x%X: 0x%X\nmust have the low 2 bits set to 01\n",virtual(IPR(SCBB) + interrupt_vector_offset),new_pc.vector_as_long); } stop = 1; return; } } if(!IS) { IPR(CMD) = SP; /*Save the current stack pointer in internal processor register equal to the current mode*/ IPR(CMD+KFP) = FP; /*Save the current frame pointer in internal processor register equal to the current mode*/ if( SERVICED_ON(new_pc) == 0) /*Check low bit of vector to see if interrupt or kernel stack*/ SP = IPR(KSP); /*set the stack pointer to the kernel stack pointer*/ else /*interrupt stack*/ { SP = IPR(ISP); /*set stack pointer to interrupt stack poiner address*/ IS = 1; /*set using Interrupt stack flag*/ } } PMD = KSP; /*clear the Previous mode bits of PSL*/ CMD = KSP; /*clear the Current mode bits of PSL*/ SP -= 4; vax_putl( old_psl, SP ); SP -= 4; if(FPD) vax_putl( old_pc, SP ); else vax_putl( PC, SP ); PC = HANDLER_ADDRESS(new_pc); CM = TP = FPD = DV = FU = IV = T = N = Z = V = C = 0; IPL = new_ipl; if(PC == 0) { aprintf("Interrupt\nHalted No Vector defined\n\nVector Address 0x%X: 0x%X",virtual(IPR(SCBB) + interrupt_vector_offset),new_pc.vector_as_long); rei("rei"); stop = 1; } }}void arithmetic_fault( long code, char *cause){ if(code < FLOATING_OVERFLOW_FAULT) /*a trap not a fault*/ exception(TRAP,V_A,cause,1,code); else exception(FAULT,V_A,cause,1,code);}