📄 armcopro.c
字号:
#endif/* Here's ARMulator's MMU definition. A few things to note: 1) It has eight registers, but only two are defined. 2) You can only access its registers with MCR and MRC. 3) MMU Register 0 (ID) returns 0x41440110 4) Register 1 only has 4 bits defined. Bits 0 to 3 are unused, bit 4 controls 32/26 bit program space, bit 5 controls 32/26 bit data space, bit 6 controls late abort timimg and bit 7 controls big/little endian. */static ARMword MMUReg[8];static unsignedMMUInit (ARMul_State * state){/* 2004-05-09 chy-------------------------------------------------------------read ARM Architecture Reference Manual2.6.5 Data AbortThere are three Abort Model in ARM arch.Early Abort Model: used in some ARMv3 and earlier implementations. In thismodel, base register wirteback occurred for LDC,LDM,STC,STM instructions, andthe base register was unchanged for all other instructions. (oldest)Base Restored Abort Model: If a Data Abort occurs in an instruction whichspecifies base register writeback, the value in the base register isunchanged. (strongarm, xscale)Base Updated Abort Model: If a Data Abort occurs in an instruction whichspecifies base register writeback, the base register writeback still occurs.(arm720T)read PART Bchap2 The System Control Coprocessor CP152.4 Register1:control registerL(bit 6): in some ARMv3 and earlier implementations, the abort model of theprocessor could be configured:0=early Abort Model Selected(now obsolete)1=Late Abort Model selceted(same as Base Updated Abort Model)on later processors, this bit reads as 1 and ignores writes.-------------------------------------------------------------So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) if lateabtSig=0, then it means Base Restored Abort Modelbecause the ARMs which skyeye simulates are all belonged to ARMv4,so I think MMUReg[1]'s bit 6 should always be 1*/ MMUReg[1] = state->prog32Sig << 4 | state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7; //state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7; ARMul_ConsolePrint (state, ", MMU present"); return TRUE;}static unsignedMMUMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value){ mmu_mrc (state, instr, value); return (ARMul_DONE);}static unsignedMMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value){ mmu_mcr (state, instr, value); return (ARMul_DONE);}#if 0static unsignedMMUMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value){ int reg = BITS (16, 19) & 7; if (reg == 0) *value = 0x41440110; else *value = MMUReg[reg]; return ARMul_DONE;}static unsignedMMUMCR (ARMul_State * state, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value){ int reg = BITS (16, 19) & 7; MMUReg[reg] = value; if (reg == 1) { ARMword p, d, l, b; p = state->prog32Sig; d = state->data32Sig; l = state->lateabtSig; b = state->bigendSig; state->prog32Sig = value >> 4 & 1; state->data32Sig = value >> 5 & 1; state->lateabtSig = value >> 6 & 1; state->bigendSig = value >> 7 & 1; if (p != state->prog32Sig || d != state->data32Sig || l != state->lateabtSig || b != state->bigendSig) /* Force ARMulator to notice these now. */ state->Emulate = CHANGEMODE; } return ARMul_DONE;}static unsignedMMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value){ if (reg == 0) *value = 0x41440110; else if (reg < 8) *value = MMUReg[reg]; return TRUE;}static unsignedMMUWrite (ARMul_State * state, unsigned reg, ARMword value){ if (reg < 8) MMUReg[reg] = value; if (reg == 1) { ARMword p, d, l, b; p = state->prog32Sig; d = state->data32Sig; l = state->lateabtSig; b = state->bigendSig; state->prog32Sig = value >> 4 & 1; state->data32Sig = value >> 5 & 1; state->lateabtSig = value >> 6 & 1; state->bigendSig = value >> 7 & 1; if (p != state->prog32Sig || d != state->data32Sig || l != state->lateabtSig || b != state->bigendSig) /* Force ARMulator to notice these now. */ state->Emulate = CHANGEMODE; } return TRUE;}#endif/* What follows is the Validation Suite Coprocessor. It uses two co-processor numbers (4 and 5) and has the follwing functionality. Sixteen registers. Both co-processor nuimbers can be used in an MCR and MRC to access these registers. CP 4 can LDC and STC to and from the registers. CP 4 and CP 5 CDP 0 will busy wait for the number of cycles specified by a CP register. CP 5 CDP 1 issues a FIQ after a number of cycles (specified in a CP register), CDP 2 issues an IRQW in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5 stores a 32 bit time value in a CP register (actually it's the total number of N, S, I, C and F cyles). */static ARMword ValReg[16];static unsignedValLDC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type, ARMword instr, ARMword data){ static unsigned words; if (type != ARMul_DATA) words = 0; else { ValReg[BITS (12, 15)] = data; if (BIT (22)) /* It's a long access, get two words. */ if (words++ != 4) return ARMul_INC; } return ARMul_DONE;}static unsignedValSTC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type, ARMword instr, ARMword * data){ static unsigned words; if (type != ARMul_DATA) words = 0; else { *data = ValReg[BITS (12, 15)]; if (BIT (22)) /* It's a long access, get two words. */ if (words++ != 4) return ARMul_INC; } return ARMul_DONE;}static unsignedValMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value){ *value = ValReg[BITS (16, 19)]; return ARMul_DONE;}static unsignedValMCR (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value){ ValReg[BITS (16, 19)] = value; return ARMul_DONE;}static unsignedValCDP (ARMul_State * state, unsigned type, ARMword instr){ static unsigned int finish = 0; if (BITS (20, 23) != 0) return ARMul_CANT; if (type == ARMul_FIRST) { ARMword howlong; howlong = ValReg[BITS (0, 3)]; /* First cycle of a busy wait. */ finish = ARMul_Time (state) + howlong; return howlong == 0 ? ARMul_DONE : ARMul_BUSY; } else if (type == ARMul_BUSY) { if (ARMul_Time (state) >= finish) return ARMul_DONE; else return ARMul_BUSY; } return ARMul_CANT;}static unsignedDoAFIQ (ARMul_State * state){ state->NfiqSig = LOW; return 0;}static unsignedDoAIRQ (ARMul_State * state){ state->NirqSig = LOW; return 0;}static unsignedIntCDP (ARMul_State * state, unsigned type, ARMword instr){ static unsigned int finish; ARMword howlong; howlong = ValReg[BITS (0, 3)]; switch ((int) BITS (20, 23)) { case 0: if (type == ARMul_FIRST) { /* First cycle of a busy wait. */ finish = ARMul_Time (state) + howlong; return howlong == 0 ? ARMul_DONE : ARMul_BUSY; } else if (type == ARMul_BUSY) { if (ARMul_Time (state) >= finish) return ARMul_DONE; else return ARMul_BUSY; } return ARMul_DONE; case 1: if (howlong == 0) ARMul_Abort (state, ARMul_FIQV); else ARMul_ScheduleEvent (state, howlong, DoAFIQ); return ARMul_DONE; case 2: if (howlong == 0) ARMul_Abort (state, ARMul_IRQV); else ARMul_ScheduleEvent (state, howlong, DoAIRQ); return ARMul_DONE; case 3: state->NfiqSig = HIGH; return ARMul_DONE; case 4: state->NirqSig = HIGH; return ARMul_DONE; case 5: ValReg[BITS (0, 3)] = ARMul_Time (state); return ARMul_DONE; } return ARMul_CANT;}/* Install co-processor instruction handlers in this routine. */unsignedARMul_CoProInit (ARMul_State * state){ unsigned int i; /* Initialise tham all first. */ for (i = 0; i < 16; i++) ARMul_CoProDetach (state, i); /* Install CoPro Instruction handlers here. The format is: ARMul_CoProAttach (state, CP Number, Init routine, Exit routine LDC routine, STC routine, MRC routine, MCR routine, CDP routine, Read Reg routine, Write Reg routine). */ if (state->is_ep9312) { ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4, DSPMRC4, DSPMCR4, DSPCDP4, NULL, NULL); ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5, DSPMRC5, DSPMCR5, DSPCDP5, NULL, NULL); ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL, DSPMRC6, DSPMCR6, DSPCDP6, NULL, NULL); } else { ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC, ValMRC, ValMCR, ValCDP, NULL, NULL); ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL, ValMRC, ValMCR, IntCDP, NULL, NULL); } if (state->is_XScale) { //chy 2005-09-19, for PXA27x's CP6 if (state->is_pxa27x) { ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL, xscale_cp6_mrc, NULL, NULL, NULL, NULL); } //chy 2005-09-19 end------------- ARMul_CoProAttach (state, 13, xscale_cp13_init, xscale_cp13_exit, xscale_cp13_ldc, xscale_cp13_stc, xscale_cp13_mrc, xscale_cp13_mcr, xscale_cp13_cdp, xscale_cp13_read_reg, xscale_cp13_write_reg); ARMul_CoProAttach (state, 14, xscale_cp14_init, xscale_cp14_exit, xscale_cp14_ldc, xscale_cp14_stc, xscale_cp14_mrc, xscale_cp14_mcr, xscale_cp14_cdp, xscale_cp14_read_reg, xscale_cp14_write_reg); //chy: 2003-08-24. ARMul_CoProAttach (state, 15, xscale_cp15_init, xscale_cp15_exit, xscale_cp15_ldc, xscale_cp15_stc, xscale_cp15_mrc, xscale_cp15_mcr, xscale_cp15_cdp, xscale_cp15_read_reg, xscale_cp15_write_reg); } else { //all except xscale ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL, // MMUMRC, MMUMCR, NULL, MMURead, MMUWrite); MMUMRC, MMUMCR, NULL, NULL, NULL); }//chy 2003-09-03 do it in future!!!!????#if 0 if (state->is_iWMMXt) { ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC, NULL, NULL, IwmmxtCDP, NULL, NULL); ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, NULL); }#endif //----------------------------------------------------------------------------- //chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code. ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL, ValMRC, ValMCR, NULL, NULL, NULL); ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC, NULL, NULL, NULL, NULL, NULL); //------------------------------------------------------------------------------ /* No handlers below here. */ /* Call all the initialisation routines. */ for (i = 0; i < 16; i++) if (state->CPInit[i]) (state->CPInit[i]) (state); return TRUE;}/* Install co-processor finalisation routines in this routine. */voidARMul_CoProExit (ARMul_State * state){ register unsigned i; for (i = 0; i < 16; i++) if (state->CPExit[i]) (state->CPExit[i]) (state); for (i = 0; i < 16; i++) /* Detach all handlers. */ ARMul_CoProDetach (state, i);}/* Routines to hook Co-processors into ARMulator. */voidARMul_CoProAttach (ARMul_State * state, unsigned number, ARMul_CPInits * init, ARMul_CPExits * exit, ARMul_LDCs * ldc, ARMul_STCs * stc, ARMul_MRCs * mrc, ARMul_MCRs * mcr, ARMul_CDPs * cdp, ARMul_CPReads * read, ARMul_CPWrites * write){ if (init != NULL) state->CPInit[number] = init; if (exit != NULL) state->CPExit[number] = exit; if (ldc != NULL) state->LDC[number] = ldc; if (stc != NULL) state->STC[number] = stc; if (mrc != NULL) state->MRC[number] = mrc; if (mcr != NULL) state->MCR[number] = mcr; if (cdp != NULL) state->CDP[number] = cdp; if (read != NULL) state->CPRead[number] = read; if (write != NULL) state->CPWrite[number] = write;}voidARMul_CoProDetach (ARMul_State * state, unsigned number){ ARMul_CoProAttach (state, number, NULL, NULL, NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R, NoCoPro3R, NULL, NULL); state->CPInit[number] = NULL; state->CPExit[number] = NULL; state->CPRead[number] = NULL; state->CPWrite[number] = NULL;}//chy 2003-09-03:below funs just replace the old ones/* Set the XScale FSR and FAR registers. */voidXScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword _far){ //if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0) if (!state->is_XScale) return; //assume opcode2=0 crm =0 xscale_cp15_write_reg (state, 5, fsr); xscale_cp15_write_reg (state, 6, _far);}//chy 2003-09-03 seems 0 is CANT, 1 is DONE ????intXScale_debug_moe (ARMul_State * state, int moe){ //chy 2003-09-03 , W/R CP14 reg, now it's no use ???? printf ("SKYEYE: XScale_debug_moe called !!!!\n"); return 1;}#if 0//chy 2003-09-03 : only called by iwmmxt.c!!!!//chy assume opcode_2=0/* Return the value in a cp15 register. */ARMwordread_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm){ unsigned value; if (reg != 15) { printf ("SKYEYE: read_cp15_reg read other reg 0x%x \n", reg); exit (-1); } xscale_cp15_read_reg (reg, &value); printf ("SKYEYE: read_cp15_reg read reg 0x%x, val 0x%x \n", reg, value); return value;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -