void dae_process(struct trapframe *eframe, u_int x, u_int dmax, u_int dmdx, u_int dmtx) { u_int v, reg; if (!ISSET(dmtx, DMT_VALID)) return; DAE_DEBUG( if (ISSET(dmtx, DMT_WRITE)) printf("[DMT%d=%x: st.%c %x to %x as %d %s %s]\n", x, dmtx, dmtx & DMT_DAS ? 's' : 'u', dmdx, dmax, DMT_ENBITS(dmtx), dmtx & DMT_DOUB1 ? "double": "not double", dmtx & DMT_LOCKBAR ? "xmem": "not xmem"); else printf("[DMT%d=%x: ld.%c r%d <- %x as %d %s %s]\n", x, dmtx, dmtx & DMT_DAS ? 's' : 'u', DMT_DREGBITS(dmtx), dmax, DMT_ENBITS(dmtx), dmtx & DMT_DOUB1 ? "double": "not double", dmtx & DMT_LOCKBAR ? "xmem": "not xmem") ); dmax += dmt_en_info[DMT_ENBITS(dmtx)].offset; reg = DMT_DREGBITS(dmtx); if (!ISSET(dmtx, DMT_LOCKBAR)) { /* the fault is not during an XMEM */ if (x == 2 && ISSET(dmtx, DMT_DOUB1)) { /* pipeline 2 (earliest stage) for a double */ if (ISSET(dmtx, DMT_WRITE)) { /* * STORE DOUBLE WILL BE REINITIATED BY rte */ } else { /* EMULATE ld.d INSTRUCTION */ v = do_load_word(dmax, dmtx & DMT_DAS); if (reg != 0) eframe->tf_r[reg] = v; v = do_load_word(dmax ^ 4, dmtx & DMT_DAS); if (reg != 31) eframe->tf_r[reg + 1] = v; } } else { /* not pipeline #2 with a double */ if (dmtx & DMT_WRITE) { switch (dmt_en_info[DMT_ENBITS(dmtx)].size) { case DMT_BYTE: DAE_DEBUG( printf("[byte %x -> [%x(%c)]\n", dmdx & 0xff, dmax, ISSET(dmtx, DMT_DAS) ? 's' : 'u') ); do_store_byte(dmax, dmdx, dmtx & DMT_DAS); break; case DMT_HALF: DAE_DEBUG( printf("[half %x -> [%x(%c)]\n", dmdx & 0xffff, dmax, ISSET(dmtx, DMT_DAS) ? 's' : 'u') ); do_store_half(dmax, dmdx, dmtx & DMT_DAS); break; case DMT_WORD: DAE_DEBUG( printf("[word %x -> [%x(%c)]\n", dmdx, dmax, ISSET(dmtx, DMT_DAS) ? 's' : 'u') ); do_store_word(dmax, dmdx, dmtx & DMT_DAS); break; } } else { /* else it's a read */ switch (dmt_en_info[DMT_ENBITS(dmtx)].size) { case DMT_BYTE: v = do_load_byte(dmax, dmtx & DMT_DAS); if (!ISSET(dmtx, DMT_SIGNED)) v &= 0x000000ff; break; case DMT_HALF: v = do_load_half(dmax, dmtx & DMT_DAS); if (!ISSET(dmtx, DMT_SIGNED)) v &= 0x0000ffff; break; case DMT_WORD: v = do_load_word(dmax, dmtx & DMT_DAS); break; } DAE_DEBUG( if (reg == 0) printf("[no write to r0 done]\n"); else printf("[r%d <- %x]\n", reg, v); ); if (reg != 0) eframe->tf_r[reg] = v; } } } else {
void data_access_emulation(unsigned *eframe) { register int x; register struct dmt_reg *dmtx; register unsigned dmax, dmdx; register unsigned v, reg; if (!(eframe[EF_DMT0] & DMT_VALID)) return; for (x = 0; x < 3; x++) { dmtx = (struct dmt_reg *)&eframe[EF_DMT0+x*3]; if (!dmtx->dmt_valid) continue; dmdx = eframe[EF_DMD0+x*3]; dmax = eframe[EF_DMA0+x*3]; DAE_DEBUG ( if (dmtx->dmt_write) DEBUG_MSG("[DMT%d=%x: st.%c %x to %x as [%s] %s %s]\n", x, eframe[EF_DMT0+x*3], dmtx->dmt_das ? 's' : 'u', dmdx, dmax, bytes[dmtx->dmt_en], dmtx->dmt_doub1 ? "double": "not double", dmtx->dmt_lockbar ? "xmem": "not xmem"); else DEBUG_MSG("[DMT%d=%x: ld.%c r%d<-%x as [%s] %s %s]\n", x, eframe[EF_DMT0+x*3], dmtx->dmt_das ? 's' : 'u', dmtx->dmt_dreg, dmax, bytes[dmtx->dmt_en], dmtx->dmt_doub1 ? "double": "not double", dmtx->dmt_lockbar ? "xmem": "not xmem"); ) dmax += dmt_en_info[dmtx->dmt_en].offset; reg = dmtx->dmt_dreg; if ( ! dmtx->dmt_lockbar) { /* the fault is not during an XMEM */ if (x == 2 && dmtx->dmt_doub1) { /* pipeline 2 (earliest stage) for a double */ if (dmtx->dmt_write) { /* STORE DOUBLE WILL BE RE-INITIATED BY rte */ } else { /* EMULATE ld.d INSTRUCTION */ v = do_load_word(dmax, dmtx->dmt_das); if (reg != 0) eframe[EF_R0 + reg] = v; v = do_load_word(dmax ^ 4, dmtx->dmt_das); if (reg != 31) eframe[EF_R0 + reg + 1] = v; } } else /* not pipeline #2 with a double */ { if (dmtx->dmt_write) switch (dmt_en_info[dmtx->dmt_en].size) { case DMT_BYTE: DAE_DEBUG(DEBUG_MSG("[byte %x -> [%x(%c)]\n", dmdx & 0xff, dmax, dmtx->dmt_das ? 's' : 'u')) do_store_byte(dmax, dmdx, dmtx->dmt_das); break; case DMT_HALF: DAE_DEBUG(DEBUG_MSG("[half %x -> [%x(%c)]\n", dmdx & 0xffff, dmax, dmtx->dmt_das ? 's' : 'u')) do_store_half(dmax, dmdx, dmtx->dmt_das); break; case DMT_WORD: DAE_DEBUG(DEBUG_MSG("[word %x -> [%x(%c)]\n", dmdx, dmax, dmtx->dmt_das ? 's' : 'u')) do_store_word(dmax, dmdx, dmtx->dmt_das); break; } else /* else it's a read */ { switch (dmt_en_info[dmtx->dmt_en].size) { case DMT_BYTE: v = do_load_byte(dmax, dmtx->dmt_das); if (!dmtx->dmt_signed) v &= 0x000000ff; break; case DMT_HALF: v = do_load_half(dmax, dmtx->dmt_das); if (!dmtx->dmt_signed) v &= 0x0000ffff; break; case DMT_WORD: default: /* 'default' just to shut up lint */ v = do_load_word(dmax, dmtx->dmt_das); break; } if (reg == 0) { DAE_DEBUG(DEBUG_MSG("[no write to r0 done]\n")); } else { DAE_DEBUG(DEBUG_MSG("[r%d <- %x]\n", reg, v)); eframe[EF_R0 + reg] = v; } } } } else /* if lockbar is set... it's part of an XMEM */ { /* * According to Motorola's "General Information", * the dmt_doub1 bit is never set in this case, as it should be. * They call this "general information" - I call it a f*cking bug! * * Anyway, if lockbar is set (as it is if we're here) and if * the write is not set, then it's the same as if doub1 * was set... */ if ( ! dmtx->dmt_write) { if (x != 2) { /* RERUN xmem WITH DMD(x+1) */ x++; dmdx = eframe[EF_DMD0 + x*3]; } else { /* RERUN xmem WITH DMD2 */ } if (dmt_en_info[dmtx->dmt_en].size == DMT_WORD) v = do_xmem_word(dmax, dmdx, dmtx->dmt_das); else v = do_xmem_byte(dmax, dmdx, dmtx->dmt_das); eframe[EF_R0 + reg] = v; } else { if (x == 0) { eframe[EF_R0 + reg] = dmdx; eframe[EF_SFIP] = eframe[EF_SNIP]; eframe[EF_SNIP] = eframe[EF_SXIP]; eframe[EF_SXIP] = 0; /* xmem RERUN ON rte */ eframe[EF_DMT0] = 0; return; } } } }
void data_access_emulation(unsigned *eframe) { int x; unsigned dmax, dmdx, dmtx; unsigned v, reg; dmtx = eframe[EF_DMT0]; if (!ISSET(dmtx, DMT_VALID)) return; for (x = 0; x < 3; x++) { dmtx = eframe[EF_DMT0 + x * 3]; if (!ISSET(dmtx, DMT_VALID) || ISSET(dmtx, DMT_SKIP)) continue; dmdx = eframe[EF_DMD0 + x * 3]; dmax = eframe[EF_DMA0 + x * 3]; DAE_DEBUG( if (ISSET(dmtx, DMT_WRITE)) printf("[DMT%d=%x: st.%c %x to %x as %d %s %s]\n", x, dmtx, dmtx & DMT_DAS ? 's' : 'u', dmdx, dmax, DMT_ENBITS(dmtx), dmtx & DMT_DOUB1 ? "double": "not double", dmtx & DMT_LOCKBAR ? "xmem": "not xmem"); else printf("[DMT%d=%x: ld.%c r%d <- %x as %d %s %s]\n", x, dmtx, dmtx & DMT_DAS ? 's' : 'u', DMT_DREGBITS(dmtx), dmax, DMT_ENBITS(dmtx), dmtx & DMT_DOUB1 ? "double": "not double", dmtx & DMT_LOCKBAR ? "xmem": "not xmem") ); dmax += dmt_en_info[DMT_ENBITS(dmtx)].offset; reg = DMT_DREGBITS(dmtx); if (!ISSET(dmtx, DMT_LOCKBAR)) { /* the fault is not during an XMEM */ if (x == 2 && ISSET(dmtx, DMT_DOUB1)) { /* pipeline 2 (earliest stage) for a double */ if (ISSET(dmtx, DMT_WRITE)) { /* * STORE DOUBLE WILL BE REINITIATED * BY rte */ } else { /* EMULATE ld.d INSTRUCTION */ v = do_load_word(dmax, dmtx & DMT_DAS); if (reg != 0) eframe[EF_R0 + reg] = v; v = do_load_word(dmax ^ 4, dmtx & DMT_DAS); if (reg != 31) eframe[EF_R0 + reg + 1] = v; } } else { /* not pipeline #2 with a double */ if (dmtx & DMT_WRITE) { switch (dmt_en_info[DMT_ENBITS(dmtx)].size) { case DMT_BYTE: DAE_DEBUG( printf("[byte %x -> [%x(%c)]\n", dmdx & 0xff, dmax, ISSET(dmtx, DMT_DAS) ? 's' : 'u') ); do_store_byte(dmax, dmdx, dmtx & DMT_DAS); break; case DMT_HALF: DAE_DEBUG( printf("[half %x -> [%x(%c)]\n", dmdx & 0xffff, dmax, ISSET(dmtx, DMT_DAS) ? 's' : 'u') ); do_store_half(dmax, dmdx, dmtx & DMT_DAS); break; case DMT_WORD: DAE_DEBUG( printf("[word %x -> [%x(%c)]\n", dmdx, dmax, ISSET(dmtx, DMT_DAS) ? 's' : 'u') ); do_store_word(dmax, dmdx, dmtx & DMT_DAS); break; } } else { /* else it's a read */ switch (dmt_en_info[DMT_ENBITS(dmtx)].size) { case DMT_BYTE: v = do_load_byte(dmax, dmtx & DMT_DAS); if (!ISSET(dmtx, DMT_SIGNED)) v &= 0x000000ff; break; case DMT_HALF: v = do_load_half(dmax, dmtx & DMT_DAS); if (!ISSET(dmtx, DMT_SIGNED)) v &= 0x0000ffff; break; case DMT_WORD: v = do_load_word(dmax, dmtx & DMT_DAS); break; } DAE_DEBUG( if (reg == 0) printf("[no write to r0 done]\n"); else printf("[r%d <- %x]\n", reg, v); ); if (reg != 0) eframe[EF_R0 + reg] = v; } } } else { /* if lockbar is set... it's part of an XMEM */ /* * According to Motorola's "General Information", * the DMT_DOUB1 bit is never set in this case, as it * should be. * If lockbar is set (as it is if we're here) and if * the write is not set, then it's the same as if DOUB1 * was set... */ if (!ISSET(dmtx, DMT_WRITE)) {