📄 main_run.c
字号:
STACK_SAVE_REGS; SAVE_SHADOW_REGS; SAVE_QC_REWIND; SAVE_JUMPPC; OUT_OF_TC; CORRECT_OUTGOING_CC(a3); SPILL_FP_IF_ENABLED; v_movu(a2, sim_t1); v_ldui(a3, vss_base, MYNUM_OFF); /* a3 CC correction already saved */ v_setl(t9, (unsigned) phys_mem_ref); v_jalp(ra, t9); v_movu(sim_t1, v0); /* we need to restore to v0 */ CORRECT_INCOMING_CC; RESTORE_QC_REWIND; STACK_RESTORE_REGS; RESTORE_SHADOW_REGS; ENTERING_TC; /* If c_mem_ref_wrapper returns non-zero issue that address */ /* This allows access to backdoor data */ /* Note that instruction misses always rewind the quickcheck */ /* because we don't fetch instructions from the backdoor */ v_bneui(sim_t1, 0, pmr_label); v_addu(ra, ra, sim_t2); /* REWIND QUICK CHECK */ v_addui(ra, ra, 8); /* 2 more instructions: jal, delay slot */ v_label(pmr_label); v_jp(ra); /* we need this for label to work */ v_nop(); return ((mar_ptr) v_end(used).v);} mar_ptr Genpa_mem_ref_wrapper(char *buf, int size, int *used){ static v_label_t pamr_label; v_lambda("pa_mem_ref_wrapper", "", 0, V_LEAF, (v_code *) buf, size); pamr_label = v_genlabel(); /* a0 contains virtual address of reference, a2 contains pc */ /* SIM_T1 contains the K0 address of reference, if possible */ /* SIM_T2 contains the rewind amount */ STACK_SAVE_REGS; SAVE_SHADOW_REGS; SAVE_QC_REWIND; SAVE_JUMPPC; OUT_OF_TC; CORRECT_OUTGOING_CC(a3); SPILL_FP_IF_ENABLED; v_movu(a2, sim_t1); v_ldui(a3, vss_base, MYNUM_OFF); /* a3 CC correction already saved */ v_setl(t9, (unsigned) pa_mem_ref); v_jalp(ra, t9); v_movu(sim_t1, v0); /* we need to restore to v0 */ CORRECT_INCOMING_CC; RESTORE_QC_REWIND; STACK_RESTORE_REGS; RESTORE_SHADOW_REGS; ENTERING_TC; /* If c_mem_ref_wrapper returns non-zero issue that address */ /* This allows access to backdoor data */ /* Note that instruction misses always rewind the quickcheck */ /* because we don't fetch instructions from the backdoor */ v_bneui(sim_t1, 0, pamr_label); v_addu(ra, ra, sim_t2); /* REWIND QUICK CHECK */ v_addui(ra, ra, 8); /* 2 more instructions: jal, delay slot */ v_label(pamr_label); v_jp(ra); /* we need this for label to work correctly */ v_nop(); return ((mar_ptr) v_end(used).v);}/* New 64-bit stuff from callout.s */#ifdef EMBRA_USE_QC64#define HASH_FUNC(_inreg, _treg1, _treg2) \ dsrl32(_treg2.reg,_inreg.reg,0); \ v_rshuli(_treg1,_inreg,12); \ v_xorul(_treg1,_treg1,_treg2); \ v_rshuli(_treg2,_inreg,20); \ v_xorul(_treg1,_treg1,_treg2); \ dsrl32(_treg2.reg,_inreg.reg,25); \ v_xorul(_treg1, _treg1, _treg2); \ v_andli(_treg1,_treg1,(QC64_NUM_ENTRIES-1)); mar_ptr GenQC64HashFunc(char *buf, int size, int *used){ v_lambda("pa_mem_ref_wrapper", "", 0, V_LEAF, (v_code *) buf, size); HASH_FUNC(a0,v0,v1) /* j ra */ return ((mar_ptr) v_end(used).v);}/* * Em_dynPQdsh - MMU quick check for data access shared (read). * a0 == vAddr of access * a3 == cycle correction if callout. * returns MA is SIM_T1 */ /* * Just a few comments here about what is going on. * * This is the Page Quick Check. We check to make sure that * our PC is on the right page. That is, we do a TLB lookup * on the virtual page, and hope we hit. * * Our TLB is hashed, so we hash the virtual address and use it * to look up a TLB entry. We check the TLB entry to make sure that * it is the entry for our virtual page. * * If it is, we get the physical page address, add our offset, and * we have the physical address. * * If it isn't, we call out to read the actual page table. * * Note that pages can be mapped shared(read), exclusive(write), * or instruction (read-only) -> right??? * We have a different quick check for each kind. *//* typedef struct { * VA vpn; * MA ma; * uint writable; * } QC64HashEntry; */mar_ptr GenEm_dynPQCdsh(char *buf, int size, int *used){ static v_label_t pqc_label1, pqc_label2; v_lambda("Em_dynPQCdsh", "", 0, V_LEAF, (v_code *) buf, size); pqc_label1 = v_genlabel(); pqc_label2 = v_genlabel(); HASH_FUNC(a0,a2,sim_t1); /* a2 = hash(a0) */ v_lshui(a2, a2, 4); /* x 16 */ v_addul(sim_t4, mmu_reg, a2); /* offset into TLB array */ v_ldli(a1, sim_t4, 0); /* tlb page virtual address */ v_rshuli(a2, a0, 12); /* virtual address */ v_bnel(a2, a1, pqc_label1); /* go if no match */ v_andli(a2, a0, DEFAULT_PAGESZ-1); /* get page offset */ v_ldui(sim_t1, sim_t4, 8); /* page physical base address */ v_addu(sim_t1, sim_t1, a2); /* add to offset to get real PA */ v_jp(ra); /* return */ v_label(pqc_label1); /* 1: */ /* Insert PC into state structure and callout to do lookup */ v_stli(v0, vss_base, PC_OFF); /* shouldn't this be store long??? */ v_stii(ra, vss_base, QCRA_OFF); STACK_SAVE_REGS; SAVE_SHADOW_REGS; CORRECT_OUTGOING_CC(a3); v_stli(a0, vss_base, HACKADDR_OFF); v_setl(a1, QC64_READ); v_setl(t9, ((unsigned long) Em_QC64Reload)); /* that annoying t9 convention */ v_jalpi(ra, ((unsigned long) Em_QC64Reload)); v_beqli(v0, 0, pqc_label2); v_movu(sim_t1, v0); /* delay slot??!!! */ /* shouldn't this be long also ??? */ v_ldii(ra, vss_base, QCRA_OFF); CORRECT_INCOMING_CC; STACK_RESTORE_REGS; RESTORE_SHADOW_REGS; v_jp(ra); v_label(pqc_label2); /* 8: */ v_ldii(ra, vss_base, QCRA_OFF); CORRECT_INCOMING_CC; STACK_RESTORE_REGS; RESTORE_SHADOW_REGS; /* Because we are in the same segment as TC, and we are jumping to */ /* an assembly routine, we can just use the bits directly */ v_ldli(a0, vss_base, HACKADDR_OFF); v_setl(a1, MEM_D_SHARED); ASSERT(mem_ref_wrapper != 0); v_jpi(mem_ref_wrapper); v_nop(); return ((mar_ptr) v_end(used).v);}/* exclusive (write) access */mar_ptr GenEm_dynPQCdex(char *buf, int size, int *used){ v_label_t pqc_label1, pqc_label2; v_lambda("Em_dynPQCdex", "", 0, V_LEAF, (v_code *) buf, size); pqc_label1 = v_genlabel(); pqc_label2 = v_genlabel(); HASH_FUNC(a0,a2,sim_t1); /* a2 = hash(a0) */ v_lshui(a2, a2, 4); /* x 16 */ v_addul(sim_t4, mmu_reg, a2); /* offset into TLB array */ v_ldli(a1, sim_t4, 0); /* tlb page virtual address */ v_rshuli(a2, a0, 12); /* virtual address */ v_bnel(a2, a1, pqc_label1); /* go if no match */ v_andli(a2, a0, DEFAULT_PAGESZ-1); /* get page offset */ v_ldui(a1, sim_t4, 12); /* get writable */ v_bequi(a1, 0, pqc_label1); /* go if zero */ v_ldui(sim_t1, sim_t4, 8); /* page physical base address */ v_addu(sim_t1, sim_t1, a2); /* add to offset to get real PA */ v_jp(ra); /* return */ v_label(pqc_label1); /* 1: */ /* Insert PC into state structure and callout to do lookup */ REG_ST_OP(v0, vss_base, PC_OFF); /* shouldn't this be store long??? */ v_stui(ra, vss_base, QCRA_OFF); STACK_SAVE_REGS; SAVE_SHADOW_REGS; CORRECT_OUTGOING_CC(zero); v_stli(a0, vss_base, HACKADDR_OFF); v_setl(a1, QC64_WRITE); /* fetch writable */ v_setl(t9, ((unsigned long) Em_QC64Reload)); /* that annoying t9 convention */ v_jalpi(ra, ((unsigned long) Em_QC64Reload)); v_beqli(v0, 0, pqc_label2); v_movu(sim_t1, v0); /* shouldn't this be long also ??? */ v_ldui(ra, vss_base, QCRA_OFF); CORRECT_INCOMING_CC; STACK_RESTORE_REGS; RESTORE_SHADOW_REGS; v_jp(ra); v_label(pqc_label2); /* 8: */ v_ldii(ra, vss_base, QCRA_OFF); CORRECT_INCOMING_CC; STACK_RESTORE_REGS; RESTORE_SHADOW_REGS; /* Because we are in the same segment as TC, and we are jumping to */ /* an assembly routine, we can just use the bits directly */ v_ldli(a0, vss_base, HACKADDR_OFF); v_setl(a1, MEM_D_EXCLUSIVE); ASSERT(mem_ref_wrapper != 0); v_jpi(mem_ref_wrapper); v_nop(); return ((mar_ptr) v_end(used).v);} /* * Em_HackedIPageMMUQC * a0 == vAddr of access * returns MA is SIM_T2 */ mar_ptr GenEm_HackedIPageMMUQC(char *buf, int size, int *used){ static v_label_t mmuqc64_label; v_lambda("EM_HackedIPageMMUQC", "", 0, V_LEAF, (v_code *) buf, size); mmuqc64_label = v_genlabel(); HASH_FUNC(a0,a2,sim_t2) v_lshui(a2,a2,4); v_addul(sim_t4,mmu_reg,a2); v_ldli(a1,sim_t4,0); v_rshuli(a2,a0,12); v_bnei(a2, a1, mmuqc64_label); v_ldui(sim_t2,sim_t4,8); v_jp(ra); /* 1: */ v_label(mmuqc64_label); /* Insert PC into state structure */ REG_ST_OP(a0, vss_base, PC_OFF); STACK_SAVE_REGS; SAVE_SHADOW_REGS; CORRECT_OUTGOING_CC(zero); v_setl(a1, QC64_READ); /* read-only fetch*/ v_setl(t9, ((unsigned long)Em_QC64Reload));/* that annoying t9 convention */ v_jalpi(ra,Em_QC64Reload); v_ldui(ra, vss_base,QCRA_OFF); CORRECT_INCOMING_CC; STACK_RESTORE_REGS; RESTORE_SHADOW_REGS; v_rshui(v0, v0,12); v_lshui(sim_t2, v0, 12); /* j ra */ return ((mar_ptr) v_end(used).v); } #endif /* EMBRA_USE_QC64 *//* GenInterfaceCode(): generate low-level code for Embra. * We call a number of routines, each of which dynamically generates * code for a particular routine, and set a pointer to the entry * point the new routine. * * Unfortunately, these must be generated in order. Mutual * recursion is not possible at this time, unless both routines * are generated at the same time. */void GenInterfaceCode(void){ char *buf = (char *) TC_GetTCPtr( 2 ); char *start = buf; /* keep track of start for flush */ int size = 16384; /* FIX THIS amount of space left */ int used; /* amount used by routine */ InterfaceInitRegs(); /* SpillFP is used by SPILL_FP_IF_ENABLED */ SpillFP = GenSpillFP(buf, size, &used); buf += used; size -= used; RestoreFP = GenRestoreFP(buf, size, &used); buf += used; size -= used; GeneralEmEventPollasm = GenGeneralEmEventPollasm(buf, size, &used); buf += used; size -= used; UPperiodic_callout = GenUPperiodic_callout(buf, size, &used); buf += used; size -= used; IncCCasm = GenIncCCasm(buf, size, &used); buf += used; size -= used; /* Used by EmEventPoll, etc. */ Embra_CX_nochain = GenEmbra_CX_nochain(buf, size, &used); buf += used; size -= used; /* This routine is used by GenEnterTC */ continue_run_without_chaining = Gencontinue_run_without_chaining(buf, size, &used); buf += used; size -= used; continue_run = Gencontinue_run(buf, size, &used); buf += used; size -= used; /* Context switch; used by ReenterTC_CX */ Embra_CX = GenEmbra_CX(buf, size, &used); buf += used; size -= used; EnterTC = GenEnterTC(buf, size, &used); buf += used; size -= used; EnterTC_CX = GenEnterTC_CX(buf, size, &used); buf += used; size -= used; EmEventPoll = GenEmEventPoll(buf, size, &used); buf += used; size -= used; callout = Gencallout(buf, size, &used); buf += used; size -= used; mem_ref_wrapper = Genmem_ref_wrapper(buf, size, &used); buf += used; size -= used; phys_mem_ref_wrapper = Genphys_mem_ref_wrapper(buf, size, &used); buf += used; size -= used; pa_mem_ref_wrapper = Genpa_mem_ref_wrapper(buf, size, &used); buf += used; size -= used;#ifdef EMBRA_USE_QC64 QC64HashFunc = GenQC64HashFunc(buf, size, &used); buf += used; size -= used; Em_dynPQCdsh = GenEm_dynPQCdsh(buf, size, &used); buf += used; size -= used; Em_dynPQCdex = GenEm_dynPQCdex(buf, size, &used); buf += used; size -= used; Em_HackedIPageMMUQC = GenEm_HackedIPageMMUQC(buf, size, &used); buf += used; size -= used;#endif /* Flush cache in case vcode didn't */ TC_SetTCNext(2, (TCA) start, (TCA) buf); }char *main_run_sym_lookup(void *addr){ int i; char *result = "unknown"; void *last = 0; void *cur; for (i = 0; i < (sizeof(main_run_syms)/sizeof(main_run_sym)); i++) { cur = main_run_syms[i].addr; if (cur < addr && cur > last) { last = cur; result = main_run_syms[i].name; } } return result;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -