⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 translator.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifndef EMBRA_USE_QC64              ASSERT( !IS_MMU_PROT_WRITE(QC_MMU_LOOKUP(curEmp,curEmp->PC)));#endif   } #if defined(SIM_MIPS64)        ASSERT( IS_KSEG0(curEmp->PC) || IS_KUSEG(curEmp->PC) || IS_KSEG2(curEmp->PC));#endif   #if CHECKREGS      if (check_regs) {     CheckRegs((unsigned) targetTCA, (unsigned) new_pc, 0);     /* don't chain */     return targetTCA;   }#endif      /* no chaining for now!! */   if (!jump_addr) {       /*       * no chaining. simply return the targetTCA       */      return targetTCA;   }   if( ((uint)jump_addr ) == (uint)Embra_CX_nochain ) {      STAT_INC(chain_bounced);      return targetTCA;   }   if (!TC_InTC(TC_USER,jump_addr)  && !TC_InTC(TC_KERN,jump_addr)) {      CPUWarning("EmbraChaining: %10lld cpu=%d PC=0x%llx chaining from 0x%x\n",                   (uint64)EmbraCpuCycleCount(curEmp->myNum),                 curEmp->myNum,(Reg64)curEmp->PC,                 jump_addr);      return targetTCA;   }#if CHECK_INTER_TC_CHAIN   if ((TC_InTC(TC_USER,jump_addr)  && TC_InTC(TC_KERN,targetTCA)) ||       (TC_InTC(TC_KERN,jump_addr) && TC_InTC(TC_USER,targetTCA))) {      CPUError("EmbraChaining: inter-TC chain at %10lld cpu=%d PC=0x%llx chaining from 0x%x to 0x%x\n",                   (uint64)EmbraCpuCycleCount(curEmp->myNum),                 curEmp->myNum,(Reg64)curEmp->PC,                 jump_addr, targetTCA);      return targetTCA;   }#endif          /* For regind we need to chain to speculative entry point; otherwise,    * we can do better    */   if( MIPS_ISNT_REGIND(jump_addr) ) {      /*        * get the translation for the page of the previous pc.       * we need to decode it once more       */#ifdef EMBRA_USE_QC64      MA memAddr =  (MA) ((uint)Em_QC64Reload(curEmp->oldPC,QC64_READ) &                            ~(DEFAULT_PAGESZ-1));#else      MA memAddr = MMU2ADDR(QC_MMU_LOOKUP(curEmp,curEmp->oldPC));#endif      VA endOldBB = (memAddr?EndOfBB(curEmp->oldPC,memAddr+(curEmp->oldPC & (DEFAULT_PAGESZ-1))):0);      chainTCA = FindEntryPoint(curEmp->oldPC,endOldBB,new_pc,targetTCA);   } else {     /* chain to speculative entry point */      chainTCA = targetTCA;   }   /* Actually overwrite old jump instr */   ASSERT( MIPS_IS_JUMP(jump_addr) );   /* ASSERT(!TC_In_TC( (void*)(((*(unsigned*)jump_addr) & 0x3ffffff) << 2) )); */   MIPS_CHANGE_JUMP_TARGET(jump_addr, chainTCA);         FlushOneLine(jump_addr);#if 0   CPUWarning("Chain: (0x%x,0x%08x)  -> (0x%x,0x%08x) : +%d val=0x%08x\n",	      old_pc, jump_addr, curEmp->PC,chainTCA,	      (uint)chainTCA-(uint)targetTCA,	      *(unsigned*)jump_addr);#endif   return chainTCA;/* }*/}void Transfer_To(TransState *trans, VA vPC ){  TCA trans_PC;  ASSERT( !IN_BD(vPC));  switch(chainMode) {  case NO_C:     /* This jumps directly to dispatch.  Since NO_C is set, chaining */     /* is not in effect */     ECj(jal_op_, dispatchNoChain);     return;	        case BB_C:     trans_PC =  FindTCA_NoSE(trans->instrGrp->cpuNum, vPC );#if CHECKREGS     if (trans_PC && !check_regs) {#else     if (trans_PC) {#endif        VA oldPCstart = trans->instrGrp->virt_pc;        VA oldPCend   = trans->instrGrp->virt_pc +            mem_size(trans->instrGrp->GrpLen);        trans_PC = FindEntryPoint(oldPCstart,oldPCend,vPC,trans_PC);        ECj(jal_op_, trans_PC);     } else {        ECj(jal_op_, dispatchChain);     }  }}/* ******************************************************** * EmitBranch *  * Code immediately following the branch should * be for the branch NOT taken case, while * code for the branch taken case should * start after num_instr_to_skip * ********************************************************/static void Emit_Branch( TransState *trans, int num_instr_to_skip ){   int tmp1, tmp2;   /* If we can load, registers and use the branch we are translating */   if( trans->instrGrp->delay_slot_reg_conflict ) {	  ECi(bgtz_op_, G0, BRANCHREG, num_instr_to_skip);   }else{	  switch( MAJOR_OPCODE(trans->branch_instr ) ) {	  case beq_op:	  case bne_op:		 if( prev_store.real == rt(trans->branch_instr) ) {			tmp2 = Load( SIM_T2, rt(trans->branch_instr) );			tmp1 = Load( SIM_T1, rs(trans->branch_instr) );		 } else {			tmp1 = Load( SIM_T1, rs(trans->branch_instr) );			tmp2 = Load( SIM_T2, rt(trans->branch_instr) );		 }		 switch( MAJOR_OPCODE(trans->branch_instr ) ) {		 case beq_op:		   ECi(beq_op_, tmp2, tmp1, num_instr_to_skip);		   break;		 case bne_op:		   ECi(bne_op_, tmp2, tmp1, num_instr_to_skip);		   break;		 }		 break;	  case cop1_op:		 /* Kinda hacky way of changing the offset of an fp branch */	    /*** XXX THIS WILL HAVE TO BE FIXED -BL ******/		 *memptr++ = (trans->branch_instr & 0xffff0000) | num_instr_to_skip;		 break;	  default:		 tmp1 = Load(SIM_T1, rs(trans->branch_instr));		 if (MAJOR_OPCODE(trans->branch_instr) == bcond_op) {		   switch(rt(trans->branch_instr)) {		   case bltz_op:		   case bltzl_op:		     ECb(bltz_op_, tmp1, num_instr_to_skip);		     break;		   case bgez_op:		   case bgezl_op:		     ECb(bgez_op_, tmp1, num_instr_to_skip);		     break;		   default:		     fprintf(stderr,			     "Emit_Branch- unimplemented branch code = %x\n",			     rt(trans->branch_instr));		     ASSERT(0);		     break;		   }		 }		 else {		   switch (MAJOR_OPCODE(trans->branch_instr)) {		   case blez_op:		   case blezl_op:		     ECi(blez_op_, G0, tmp1, num_instr_to_skip);		     break;		   case bgtz_op:		   case bgtzl_op:		     ECi(bgtz_op_, G0, tmp1, num_instr_to_skip);		     break;		   default:		     fprintf(stderr,			   "Emit_Branch - unimplemented branch opcode = %x\n",			   MAJOR_OPCODE(trans->branch_instr));		     ASSERT(0);		     break;		   }		 }		     	  }   }}/* *********************************************************************** * Update_PC * ***********************************************************************/static void Update_PC( TransState *trans,           flow_t flow,VA next_PC ) /*flow_t flow, VA current_pc, int grp_len, VA next_PC,unsigned branch_instr,,int no_chain, int delay_slot_reg_conflict )*/{   int no_chain =  trans->instrGrp->is_rfe_block; /* || is_delay_slot_instr */   VA current_pc = trans->instrGrp->virt_pc;   switch( flow ){      case REGINDIRECT_FLOW:         /* This is a register indirect jump, so we have to return to the */         /* main simulator loop */         ASSERT( trans->branch_instr );         /* Put previous PC in OLD_PC */         /*ECs(or_op, OLD_PC, G0, PC_REG);*/         ECi(REG_ST_OP, PC_REG, VSS_BASE, OLDPC_OFF);	 /* this seems to be needed.... ??? */         ECs( or_op_, PC_REG, G0, BRANCHREG);         /* If we are returning from an exception, don't chain.  Can't */         /* chain from kernel to user space */         if( no_chain ) {            ECj(jal_op_, dispatchNoChain);         } else {            ECj(jal_op_, dispatchChain);         }	 ECnop;         break;      case SEQ_FLOW:         /* Put previous PC in OLD_PC */         /*ECs(or_op_, OLD_PC, G0, PC_REG);*/	ECi(REG_ST_OP, PC_REG, VSS_BASE, OLDPC_OFF);	ECi(ADDR_ADDI_OP, PC_REG, PC_REG, mem_size(trans->instrGrp->GrpLen) );	Transfer_To( trans, current_pc + mem_size(trans->instrGrp->GrpLen) );	ECnop;	break;      case JMP_FLOW:         /* Put previous PC in OLD_PC */         /*ECs(or_op_, OLD_PC, G0, PC_REG);*/         ECi(REG_ST_OP, PC_REG, VSS_BASE, OLDPC_OFF);#if defined(SIM_MIPS32)         ECi( lui_op_, PC_REG, G0, next_PC>>16 );	 ECi( ori_op_, PC_REG, PC_REG, next_PC );         Transfer_To( trans, next_PC );	 ECnop;#else	 {             int64 dist =  next_PC - trans->instrGrp->virt_pc;             ASSERT(dist == (int)dist);             if ((((int)dist & 0xffff8000) == 0) ||                  (((int)dist & 0xffff8000) == 0xffff8000)) {                 /* Fits in immediate field */                ECi( ADDR_ADDI_OP, PC_REG, PC_REG, (int)dist);                Transfer_To( trans, next_PC );	     } else {                Load_32_Bit_Immed(SIM_T1, dist);                ECs( ADDR_ADD_OP, PC_REG, PC_REG, SIM_T1);                Transfer_To( trans, next_PC );             }         }#endif	      break;      case BRANCH_FLOW:         /* Unconditional branches are implemented as beq $0 $0 */         if( MAJOR_OPCODE( trans->branch_instr == beq_op ) &&             rs( trans->branch_instr ) == G0 &&             rt( trans->branch_instr ) == G0 ) {            /* Put previous PC in OLD_PC */            /*ECs(or_op_, OLD_PC, G0, PC_REG);*/            ECi(REG_ST_OP, PC_REG, VSS_BASE, OLDPC_OFF);            if( ((int)(next_PC - current_pc) < (1<<15)) &&                ((int)(next_PC - current_pc) > (-(1<<15))) ) {	      ECi(ADDR_ADDI_OP, PC_REG, PC_REG, next_PC - current_pc);	      Transfer_To( trans, next_PC);	      ECnop;            }else{               Load_32_Bit_Immed(SIM_T1, next_PC - current_pc);               ECs(ADDR_ADD_OP, PC_REG, PC_REG, SIM_T1);               Transfer_To( trans, next_PC);	       ECnop;            }            break;         }         ASSERT( trans->branch_instr );         /* Both branches need the pc moved to the old PC */         /*ECs(or_op_, OLD_PC, G0, PC_REG);*/         ECi(REG_ST_OP, PC_REG, VSS_BASE, OLDPC_OFF);         Emit_Branch(trans, 3); 	 ECnop;	          /* Fall Through Case */	 ECi(ADDR_ADDI_OP, PC_REG, PC_REG, mem_size(trans->instrGrp->GrpLen) );         Transfer_To( trans, current_pc + mem_size(trans->instrGrp->GrpLen));	 ECnop;	 VCTARGET; /* branch target for vcode */	          /* Branch Taken */         if( ((int)(next_PC - current_pc) < (1<<15)) &&             ((int)(next_PC - current_pc) > (-(1<<15))) ) {            ECi(ADDR_ADDI_OP, PC_REG, PC_REG, next_PC - current_pc);            Transfer_To( trans, next_PC);	    ECnop;         }else{            Load_32_Bit_Immed(SIM_T1, next_PC - current_pc);	    ECs(ADDR_ADD_OP, PC_REG, PC_REG, SIM_T1);            Transfer_To( trans, next_PC );	    ECnop;         }         break;      case BRANCH_UNTAKEN:         ASSERT( trans->branch_instr );         /* Skip the chain if condition says, "Taken"*/         /* Put previous PC in OLD_PC */         /*ECs(or_op_, OLD_PC, G0, PC_REG);*/         ECi(REG_ST_OP, PC_REG, VSS_BASE, OLDPC_OFF);         Emit_Branch(trans, 4); /* was 3 -BL */         /* Fall Through (annulling) Case */         ECi(ADDR_ADDI_OP, PC_REG, PC_REG, mem_size(trans->instrGrp->GrpLen));         Transfer_To( trans, current_pc + mem_size(trans->instrGrp->GrpLen) );	 ECnop;	 VCTARGET; /* branch target for vcode */         break;      case BRANCH_TAKEN:         /* Previous PC in OLD_PC in the BRANCH_UNTAKEN case */         /* Branch Taken */         if( ((int)(next_PC - current_pc) < (1<<15)) &&             ((int)(next_PC - current_pc) > -(1<<15)) ) {            ECi(ADDR_ADDI_OP, PC_REG, PC_REG, next_PC - current_pc);            Transfer_To( trans, next_PC );	    ECnop;         }else{            Load_32_Bit_Immed( SIM_T1, next_PC - current_pc );            ECs(ADDR_ADD_OP, PC_REG, PC_REG, SIM_T1);            Transfer_To( trans, next_PC );	    ECnop;         }         break;      }}/*----------------------------------------------------------------------------- *   *  This section provides support for callout facilities * *---------------------------------------------------------------------------*//* XXX THIS IS WRONG!!! beware, was 7 */#define DO_EXCEPTION_CALLOUT_LEN (bogus)static void Do_Exception_Callout( TransState *trans, int exception_code){  TCA start = memptr;  PC_BD pc = COMPOSE_PC(trans);  /* Put exception code into A1 */  Load_32_Bit_Immed( A1, exception_code );  /* Put current pc into S */  ECi(ADDR_ADDI_OP, SIM_T4, PC_REG,              COMPOSE_PC(trans) - trans->instrGrp->virt_pc);  ECi(REG_ST_OP, SIM_T4, VSS_BASE, PC_OFF);  ECi(addiu_op_, A3, G0, trans->cycle_correction);  /* Put procedure number in SIM_T2 */  ECi( addiu_op_, SIM_T2, G0, CALLOUT_EXCEPTION );  /* XXX - Note we do not set A2 because it is only checked on an */  /* EXC_CPU, coprocessor unusable exception, and we do not raise */  /* those from emitted code */  /* Do the Callout */  ECj( jal_op_, callout );  ECnop;}void Do_Callout( TransState *trans,  int callout_code ){  PC_BD pc = COMPOSE_PC(trans);  TCA start = memptr;  /* Put State pointer into A0 */  /* Put current pc into A1 */  ECi(ADDR_ADDI_OP, SIM_T4, PC_REG,              COMPOSE_PC(trans) - trans->instrGrp->virt_pc);  ECi(REG_ST_OP, SIM_T4, VSS_BASE, PC_OFF);  ECi(addiu_op_, A3, G0, trans->cycle_correction);  /* Put procedure number in SIM_T2 */  ECi(addiu_op_, SIM_T2, G0, callout_code );  /* Do the Callout */  ECj( jal_op_, callout );  ECnop;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -