/************************************** * $Id: epic2.s,v 1.9 2000/03/31 20:12:00 tpeters Exp $ * * copyright @ Motorola, 1999 * **************************************/ #include "../../config.h" #ifdef GCC_REGISTERS #include "../../gcc_registers.h" #endif /* GCC_REGISTERS */ .equ sprg0, 272 .equ sprg1, 273 .equ sprg2, 274 .equ sprg3, 275 .equ hid0, 1008 .equ epicModeError, 1 .extern epicISR // In epic1.c .extern save_to_dink // In reg_swap.s .extern restore_to_dink // In reg_swap.s .extern restore_partial_dink // In reg_swap.s .extern temp_sprg0 // In except2.s .extern temp_sprg1 // In except2.s .extern dink_transfer_table // In reg_tb.c /********************************************* * function: CoreExtIntEnable * * description: Enable 603e core external interrupt * * note: mtmsr is context-synchronization **********************************************/ .text .align 2 .global CoreExtIntEnable CoreExtIntEnable: mfmsr r3 ori r3,r3,0x8000 //enable external interrupt mtmsr r3 blr /******************************************* * function: CoreExtIntDisable * * description: Disable 603e core external interrupt * * note: *******************************************/ .text .align 2 .global CoreExtIntDisable CoreExtIntDisable: mfmsr r3 lis r4,0xffff ori r4,r4,0x7fff and r3,r3,r4 //disable external interrupt mtmsr r3 blr /******************************************* * function: epicSetupTransferTable * * description: Setup r21 with the address of * dink transfer table so ISRs * can use printf. * * note: *******************************************/ .text .align 2 .global epicSetupTransferTable epicSetupTransferTable: lis r21,dink_transfer_table@h ori r21,r21,dink_transfer_table@l blr /*********************************************************** * function: exception routine called by exception vector * at 0x500, external interrupt * * description: Kahlua EPIC controller * * input: none * output: none * * note: This routine will do the following: * 1) Save the current programming model/state depending * on in_which_code flag. * 2) Call epicISR to service the interrupt * 3) Restore the programming model/state * 4) rfi back to where we where before the interrupt ***********************************************************/ .text .align 2 .global epic_exception epic_exception: // Flush and disable the icache and dcache. // This was copied from the cache flush code in handle_ex: in except2.s lis r3,0x0000 lis r4,0x0020 epicFlushHead: cmpw r3,r4 bge epicFlushDone lwz r5,0(r3) addi r3,r3,0x20 b epicFlushHead epicFlushDone: sync isync lis r4,0x8000 ori r4,r4,0xcc00 //caches on, invalidate on mtspr hid0,r4 isync sync lis r4,0x8000 ori r4,r4,0xc000 //caches on, invalidate off mtspr hid0,r4 isync sync lis r4,0x8000 ori r4,r4,0x0000 //caches off, invalidate off mtspr hid0,r4 isync sync // end of cache flush mfmsr r4 //turn on Floating Point unit in MSR ori r4,r4,0x2000 //both save_to_dink and save_to_user mtmsr r4 //save the floating point registers. // Lets find out if we were in Dink or User code so we know which // programming model to save off. lis r3,in_which_code@h //load in_which_code global ori r3,r3,in_which_code@l lwz r3,0(r3) cmpi 0,0,r3,0x0 //were we in DINK or USER code? beq cr0,saveDink // USER? save_to_user will save to the user programming model bl save_to_user b saveDone // DINK? save_to_dink will save to the dink programming model saveDink: bl save_to_dink saveDone: // restore_partial_dink (set stackpointer and bats back up) bl restore_partial_dink //this restores a bad MSR lis r3,0x0000 ori r3,r3,0x3930 //set it back to dink_msr mtmsr r3 // Now that the important registers are saved, // lets make sure we're not in Pass-through mode. // If we are in Pass-through mode, print an error // message, disable external interrupts and return. //what mode are we in? bl epicModeGet //returns mode in R3 cmpi 0,0,r3,0x1 //Direct=1, Pass-through=0 beq cr0,epicModeOK //if direct mode continue xor r3,r3,r3 ori r3,r3,epicModeError //setup error code bl epicErrorHandler //error message lis r3,current_msr@h //turn off external interrupts ori r3,r3,current_msr@l //in MSR return value to be lwz r4,0(r3) //put in SRR1 for RFI andi. r4,r4,0x7fff stw r4,0(r3) b epicRestoreReg //restore and return epicModeOK: // EPIC Interrupt Service Routine // Main routine to handle any EPIC related interrupts bl epicISR epicRestoreReg: // enable caches if they were on #ifdef ICACHEON sync isync mfspr r3,hid0 lis r4,0x8000 ori r4,r4,0x8800 // icache on, invalidate on or r3,r3,r4 lis r4,0xffff ori r4,r4,0xf7ff // icache on, invalidate off and r4,r3,r4 mtspr hid0,r3 mtspr hid0,r4 isync sync #endif #ifdef DCACHEON sync isync mfspr r3,hid0 lis r4,0x8000 ori r4,r4,0x4400 // dcache on, invalidate on or r3,r3,r4 lis r4,0xffff ori r4,r4,0xfbff // dcache on, invalidate off and r4,r3,r4 mtspr hid0,r3 mtspr hid0,r4 isync sync #endif // Check if we were in dink or user code so we know which // programming model to restore. lis r3,in_which_code@h //load in_which_code global ori r3,r3,in_which_code@l lwz r3,0(r3) cmpi 0,0,r3,0x0 //were we in DINK or USER code? beq cr0,restoreDink // USER? restore_to_user will restore the user programming model bl restore_to_user b restoreDone // DINK? restore_to_dink will restore the dink programming model restoreDink: bl restore_to_dink restoreDone: // restore saved registers that were valid prior to the exception mfspr r1,sprg1 //the restore routines leave mfspr r2,sprg2 //r1 & r2 values in sprg 1 & 2 sync lis r4,current_srr0@h ori r4,r4,current_srr0@l lwz r3,0(r4) mtspr srr0,r3 sync lis r4,current_msr@h ori r4,r4,current_msr@l lwz r3,0(r4) mtspr srr1,r3 sync lis r4,current_hid0@h ori r4,r4,current_hid0@l lwz r3,0(r4) mtspr hid0,r3 sync lis r4,current_lr@h ori r4,r4,current_lr@l lwz r3,0(r4) mtlr r3 sync lis r4,current_cr@h ori r4,r4,current_cr@l lwz r3,0(r4) mtcr r3 sync // restore_to_dink/user puts saved sprg0/1 in these temp locations lis r4,temp_sprg0@h ori r4,r4,temp_sprg0@l lwz r3,0(r4) mtspr sprg0,r3 sync lis r4,temp_sprg1@h ori r4,r4,temp_sprg1@l lwz r3,0(r4) mtspr sprg1,r3 sync lis r4,current_r5@h ori r4,r4,current_r5@l lwz r5,0(r4) sync lis r4,current_r3@h ori r4,r4,current_r3@l lwz r3,0(r4) sync lis r4,current_r4@h ori r4,r4,current_r4@l lwz r4,0(r4) sync rfi // ********* END OF FILE *********************