// Copyright Motorola, Inc. 1993, 1994 // ALL RIGHTS RESERVED // // You are hereby granted a copyright license to use, modify, and // distribute the SOFTWARE so long as this entire notice is retained // without alteration in any modified and/or redistributed versions, // and that such modified versions are clearly identified as such. // No licenses are granted by implication, estoppel or otherwise under // any patents or trademarks of Motorola, Inc. // // The SOFTWARE is provided on an "AS IS" basis and without warranty. // To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS // ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED // WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR // PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH // REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS // THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. // // To the maximum extent permitted by applicable law, IN NO EVENT SHALL // MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER // (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF // BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS // INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR // INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility // for the maintenance and support of the SOFTWARE. // // file: go_tr2.s // called from: go_tr1.c // // routines: // go_into_guts - saves dpm, loads upm, and returns // // purpose: to set up DINK32 to run the user's code // // history: // 12/29/97-- extensive rewrite for clarity -- RGP .file "go_tr2.s" #include "dink_asm.h" #include "spr_loc.h" .extern save_to_dink .extern restore_to_user // Parameters .extern special_register_file .extern offset .extern temp_reg .extern in_which_code .align 2 .global dinklink dinklink: .long 0 .set user_offset,0 .set spr_inc,8 // Icache Global Invalidate .text .align 2 .global icache_global_invalidate icache_global_invalidate: mfspr r4,hid0 // read hid0 ori r5,r4,0x0800 // set icfi bit mtspr hid0,r5 mtspr hid0,r4 // restore hid0 sync isync blr // done! // Go Benchmark -- Main routine. .text .align 2 .global go_benchmark go_benchmark: // Begin Main Routine. // This routine is used by the benchmark command to start executing // code at the address which has been placed in the UPM in SRR0 // As such it does not require that we save much of the state of DINK // since we must return through the exception handler. // Because of that we will just set up SRR0, SRR1 and perform a RFI addis r4,0,0 ori r4,r4,user_offset*4 lis r3,special_register_file@h ori r3,r3,special_register_file@l add r3,r3,r4 lwz r4,SRR0_LOC*spr_inc(r3) mtspr srr0,r4 lwz r4,SRR1_LOC*spr_inc(r3) mtspr srr1,r4 rfi // We should not return here. Rather, the lr contains // a valid return address into DINK. // Go Into Guts -- Main routine. .text .align 2 .global go_into_guts go_into_guts: // Begin Main Routine. // SPRG2 and SPRG3 will be destroyed for the common good (ie. in // order to save registers off we will need two scratch pad registers // Save the current registers (which represent DINK) into the DPM (dink // programming model) bl save_to_dink //! save off current register values into DPM // The following registers will be modified as we attempt to restore the // User's programming model into the processor: lr,cr,r3,r4. As a result // these registers will have to be set last in the epilog. The lr will be // modified as a result of the branch with link already used and r3,r4 and cr // will be modified in the routine that is branched into. // Set in_which_code to user_code since we are change context to the User's // programming model. lis r3,in_which_code@h //load variable address ori r3,r3,in_which_code@l xor r2,r2,r2 ori r2,r2,0x1 //set to user_code value stw r2,0(r3) //store to in_which_code variable bl restore_to_user //This restores GPR, FPR and SPR from //the UPM (User's Programming Model) // After call to restore_to_user above all registers have been restored except // the following: lr,r1,r2,r3 which are stored in sprg0-3 respectively. // The User's value's of sprg0 and sprg1 are stored in memory at temp_sprg0 and // temp_sprg1 respectively. We will also restore them before we jump to the // User's code. // Epilog - restore any registers which do not represent the values intended // in the user context which we are about to enter. // Specifically: // 1. Restore lr from sprg0 // 2. Restore r1 from sprg1 // 3. Use r2 and r3 to restore sprg0 and sprg1 from temp_sprg0 and temp_sprg1 // 4. Restore r2 from sprg2 // 5. Restore r3 from sprg3 // 6. Perform RFI to launch into User code at value placed in SRR0 // 1. Restore lr from sprg0 mfspr r2,sprg0 mtspr lr,r2 // 2. Restore r1 from sprg1 mfspr r1,sprg1 // 3. Use r2 and r3 to restore sprg0 and sprg1 from temp_sprg0 and temp_sprg1 lis r3,temp_sprg0@h ori r3,r3,temp_sprg0@l lwz r2,0(r3) mtspr sprg0,r2 lis r3,temp_sprg1@h ori r3,r3,temp_sprg1@l lwz r2,0(r3) mtspr sprg1,r2 // 4. Restore r2 from sprg2 mfspr r2,sprg2 // 5. Restore r3 from sprg3 mfspr r3,sprg3 // 6. Perform RFI to launch into User code at value placed in SRR0 // Execute an RFI. This will use the value of SRR0 to set the address which we // will begin executing from and move SRR1 into the MSR to establish the new // execution context. These registers should already have been set up with // these values in the UPM. rfi // We should not return here. Rather, the lr contains // a valid return address into DINK.