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

📄 translator.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
  int i;  int alloc = 0;  for(i = 0; i < NUM_ALLOCATABLE_REGS ; i++)	if( src2alloc[i]->alloc_reg )	   {		  ECi( REG_LD_OP, src2alloc[i]->alloc_reg, VSS_BASE, 			   REG_OFFSET(src2alloc[i]->reg_num) );          alloc++;	   }  return alloc;}static void Store( int used, int real){  /* No need to store to register 0 */  if( !real )    return;  ECi( REG_ST_OP, used, VSS_BASE, REG_OFFSET(real) );  /* Only use this trick with a non-allocated register */  /* XXX- Make this trick real (i.e. use register), or possibly discard */  if( used == SIM_T2 ) {	 prev_store.real = real;	 prev_store.used = used;  } else {	 prev_store.real = 0;	 prev_store.used = 0;  }}/* No matter what, store to simulated registers.  If this is an allocated register *//* then move value into the allocated register also */static void Store_Move( int contents, int store_or_alloc ){   if( reg2alloc[store_or_alloc].alloc_reg )	  ECs(or_op_, reg2alloc[store_or_alloc].alloc_reg, G0, contents);   ECi( REG_ST_OP, contents, VSS_BASE, REG_OFFSET(store_or_alloc) );}static int Set_Destination( int suggestion, int reg ){  if( !reg )    return 0;  if( reg2alloc[reg].alloc_reg )	 return reg2alloc[reg].alloc_reg;  return suggestion;}#if defined(SIM_MIPS64)static void Load_64_Bit_Immed( int reg, Reg64 immed ){  AddLongConst(immed, memptr, reg);  /* ECi(cop0_op,0,mfc_op,0);  In case we forget */  /* ECi(cop0_op,0,mfc_op,0);  to fill this in */  memptr++;  memptr++;  ASSERT(LOAD_REG_SIZE == 2);}static void FillInLongConst(void){  int i;  TCA current_memptr;  current_memptr = memptr; /* We use the EcX() macros so we need to                            * reset memptr to point at the place to                             * insert. Save current_memptr before hand.                            */  for (i = 0; i < nextLongConstIndex; i++) {     Reg64 val = longConstTable[i].value;     memptr = longConstTable[i].memptr;     if ((int64)val == (signed int)val) {        /* Is really a 32bit bit consts */        Load_32_Bit_Immed(longConstTable[i].regno, val);     } else {        /* Is 64bits - Allocate space for const at end of translation */       if (((int)current_memptr) & 0x7) current_memptr++;       (*(Reg64 *)current_memptr) = val;       ASSERT((uint)current_memptr == (Reg64)current_memptr);       Load_Op_Immed(ld_op, longConstTable[i].regno, (uint)current_memptr);       current_memptr += 2;     }  }  memptr = current_memptr;}#endif/* UGH! We will have to generate this on the fly... */extern void (*Em_dynPQCdsh)(void);extern void (*Em_dynPQCdex)(void);extern void (*Em_HackedIPageMMUQC)(VA *);#ifdef RECORD_TRANSLATIONSstatic int trans;#endifint fildes;void Translator_Init(void){   int i;   char* chainModeStr;   static int initialized;   /* I hope this is OK!! moved from below -BL */   if( initialized )     return;   initialized = 1;   /* Generate interface code */   GenInterfaceCode();      if( embra.MPinUP ) {      dispatchChain = (void *)continue_run;      dispatchNoChain = (void *)continue_run_without_chaining;      periodicCallout = (void *)Embra_CX;   } else {      dispatchChain = (void *)continue_run;      dispatchNoChain = (void *)continue_run_without_chaining;      if( TOTAL_CPUS == 1 ) {         periodicCallout = (void *)UPperiodic_callout;      } else {         periodicCallout = 0;#ifdef obsolete         periodicCallout = (void *)do_periodic_callout;#endif      }   }#if CHECKREGS   if (check_regs) fildes = open("regs",O_RDONLY);#endif   for (i = 0; i < TOTAL_CPUS; i++) {     /* XXXX evil! more hacks; init fpcr -BL */     EMP[i].FCR[0] = 0x900;  /* for R10000???? */     EMP[i].FCR[30] = 0x900; /* eir -> same as fcr0 on r10k */   }   /* XXX Hard-wire register allocation - fix this??? */   for(i = 0; i < 32; i++ )	  reg2alloc[i].reg_num = i;#ifdef RECORD_TRANSLATIONS   trans = open("./trans", (O_CREAT|O_RDWR|O_TRUNC), 0);   if( trans == -1 )	  perror("open trans");#endif   /* Make this a 1 to run without ll/sc */   chainMode = BB_C; /* BB_C or NO_C */}static void set_src2alloc( void ){   int i = 0;   int j;   /* Don't allocate register 0, and use it as a reference */   /* Registers have to be used at least once to get on the list */   reg2alloc[0].num_src = 1;   for(i = 0; i < NUM_ALLOCATABLE_REGS; i++)	  src2alloc[i] = &reg2alloc[0];   /* Exclude 0 from the running */   for(i = 1; i < 32; i++ ) {	  j = NUM_ALLOCATABLE_REGS-1;	  if( reg2alloc[i].num_src >= src2alloc[j]->num_src ) {		 src2alloc[j] = &reg2alloc[i];		 /* Bubble entry down to index 0 */		 while( j && src2alloc[j]->num_src >= src2alloc[j-1]->num_src ) {			register alloc_reg_t* tmp;			tmp = src2alloc[j];			src2alloc[j] = src2alloc[j-1];			src2alloc[j-1] = tmp;			j--;		 }	  }   }   /* Remember, don't allocate register zero, we can just use it directly */   reg2alloc[0].num_src = 0;}/* Provides a 2 instruction load from a 32 bit quantity */static void Load_Op_Immed( int loadOpCode, int reg, uint addr ){  uint low;  uint *temp = memptr;    /* Use lui and load offset to load from a 32 bit address.  We have */  /* to play games because lw sign extends its offset.  If the offset */  /* has its sign bit set, we take action to correct the value. */   ASSERT (addr >= 0x10000000);   ASSERT (addr <  0x80000000);   ASSERT ((addr < MA_TO_UINT(SIM_MEM_ADDR(0)))           || (addr >= MA_TO_UINT(SIM_MEM_ADDR(NUM_MACHINES-1) +                                  MEM_SIZE(NUM_MACHINES-1))));   if (addr & 0x8000) {     /* Correct the value computed by lw */     ECi( lui_op_, reg, 0, (addr>>16)+1 );     low = (addr & 0xffff) - (1<<16);   }   else {     ECi( lui_op_, reg, 0, (addr>>16));     low = (addr & 0xffff);   }        /* must be 16 bits for vcode !! */   ASSERT(is16bit(low));      switch (loadOpCode) {      case lb_op:	ECi( lb_op_, reg, reg, low );	break;      case lw_op:	ECi( lw_op_, reg, reg, low );	break;      case ld_op:	ECi( REG_LD_OP, reg, reg, low );	break;    }   /* we're dead if we  use more than 2 instructions */   ASSERT( memptr - temp == 2);}/*----------------------------------------------------------------------------- *   *  This section provides support for chaining * *---------------------------------------------------------------------------*//* This is a deceptively simple  function.  It emits a prelude to *//* the basic block's translation.  Only embra gods may modify it*//* XXX BL comment: Will this qualify me as an embra god?? soon!! ;-) */static void Page_Prelude_Chain_Check( InstrGrp *instrGrp,  int cycles ){   TCA start = memptr;      /* This is the bail out code, called if we should not have chained */   /* to here */   /* It can be chained, because the old ra is still in the register */   /* (and old & new pc are) correct -- except when we are coming from */   /* our exception return path, continue_run_without_chaining -- see */   /* main_run.s for details */   SET_LABEL(cont_run );   ECj(j_op_, dispatchChain);   ECnop;   /* do_periodic: we end up here when our clock goes to zero or below */   SET_LABEL(do_periodic );   ECi(addiu_op_, CLOCK_REG, CLOCK_REG, cycles);   ECj( jal_op_, periodicCallout );   ECnop;   ECi(ori_op_, RA, G0, 8); /* Smash RA from callout to prevent bogus chain ;			    * Note that chain will be to $ra-8 = 0, so no chain			    */   if (!SPECULATIVE_ENTRY)     SPECULATIVE_ENTRY = memptr - start;   ASSERT (start+SPECULATIVE_ENTRY == memptr);      start = memptr;   /* SPECULATIVE_ENTRY: */   /* Entry point number 1 is for jr (conditional chaining).  It checks */   /* virtual address match */    Load_Reg_Immed( SIM_T1, instrGrp->virt_pc );   /* If the virtual address of the last BB's target is not our VA, */   /* bail out to j continue_run;nop  */   ECilab( bne_op_, PC_REG, SIM_T1, USE_LABEL( cont_run ) );   ECnop;   if (!CHECK_MAPPING_ENTRY)     CHECK_MAPPING_ENTRY = memptr - start;   ASSERT (start+CHECK_MAPPING_ENTRY == memptr);      start = memptr;   /* CHECK_MAPPING_ENTRY: */   /* Entry point number 2 is for regular chaining.  It checks physical */   /* address match */   /* For kernel (unmapped) code, there is no mapping, so no check */   if( !IS_UNMAPPED_ADDR( instrGrp->virt_pc ) ) {#ifdef EMBRA_USE_QC64     ECi(ori_op_,SHADOW0,RA, 0); /* Save RA for chaining purpose */     ECi(ADDR_ADDI_OP, A0, PC_REG, 0); /* argument = PC */     ECj(jal_op_, Em_HackedIPageMMUQC); /* Returns in SIM_T2 */     ECi(ori_op_,RA, SHADOW0, 0); /* Restore RA for chaining purpose */#else     if( embra.MPinUP ) {       /* This code uses the actual virtual address of the current */       /* process because we can't do the faster version for MPinMP. */       /* There is such strong incentive for all dynamically linked */        /* libraries to be mapped at the same VA, that we can simply */       /* say that each VA, PA pair has its own translated block.  This */       /* allows the faster check done below. */       ECsh( srl_op_, SIM_T2, PC_REG, NUM_OFFSET_BITS );       /* Word Align */       ECsh( sll_op_, SIM_T2, SIM_T2, 2 );       ECs(addu_op_, SIM_T2, SIM_T2, MMU_REG );       ECi(lw_op_, SIM_T2, SIM_T2, 0);     } else {       Load_Op_Immed( lw_op, SIM_T2,		      (uint)&EMP[instrGrp->cpuNum].mmu[PAGE_NUMBER(instrGrp->virt_pc)] );     }#endif          Load_32_Bit_Immed( SIM_T1,  MA_TO_UINT(instrGrp->maPC)&0x7FFFF000 );          /* If the physical page corresponding to the present virtual page is */     /* not what we think know ours to be, then bail out.  */     /* Don't allow matches to pages which are set exclusive -- */     /* this implies we are executing of a page which was just */     /* written to */     ECilab( bne_op_, SIM_T1, SIM_T2, USE_LABEL( cont_run ) );     ECnop;          if (!SAME_PAGE_ENTRY)       SAME_PAGE_ENTRY = memptr - start;     /* SAME_PAGE_ENTRY: no need to check anything */     ASSERT (start + SAME_PAGE_ENTRY ==memptr);        } /* if !IS_UNMAPPED_ADDR */} /* Page_Prelude_Chain_Check *//* Comments are in Page_Prelude_Chain_Check */static void Cache_Prelude_Chain_Check( InstrGrp *instrGrp, int cycles){   uint laddr;   TCA start =memptr;   /*    * Prelude to basic block    */   SET_LABEL(cont_run );   ECj( j_op_, continue_run );   ECnop;   /* do_periodic: we end up here when our clock goes to zero or below */   SET_LABEL(do_periodic );   ECi( addiu_op_, CLOCK_REG, CLOCK_REG, cycles );   ECj( jal_op_, periodicCallout );   ECnop;   ECi(ori_op_, RA, G0, 8);  /* Smash RA from callout to prevent bogus chain */         /*ECi( REG_ST_OP, PC_REG, VSS_BASE, PC_OFF );*/   /*    * Main (first) entry point of translated BB    */   if( instrGrp->is_delay_slot_instr ) {      /* Align and adjust PC */#if defined(SIM_MIPS32)      ECsh( srl_op_, PC_REG, PC_REG, 1 );      ECsh( sll_op_, PC_REG, PC_REG, 1 );#else      ECsh( dsrl_op_, PC_REG, PC_REG, 1 );      ECsh( dsll_op_, PC_REG, PC_REG, 1 );#endif      ECi(ADDR_ADDI_OP, PC_REG, PC_REG, -4);      return;   }   if (!SPECULATIVE_ENTRY)     SPECULATIVE_ENTRY = memptr - start;   ASSERT (start+SPECULATIVE_ENTRY == memptr);      start = memptr;  /* Entry point number 1 is for jr (conditional chaining).  It checks */  /* virtual address match */   Load_Reg_Immed( SIM_T1, instrGrp->virt_pc );    /* If the virtual address of the last BB's target is not our VA, */  /* bail out to j continue_run;nop  */  ECilab( bne_op_, PC_REG, SIM_T1, USE_LABEL(cont_run) );  ECnop;    if (!CHECK_MAPPING_ENTRY)    CHECK_MAPPING_ENTRY = memptr - start;   ASSERT (start+CHECK_MAPPING_ENTRY == memptr);      start = memptr;  /* For kernel code, virtual/physical mapping is the identity map */  if( !IS_UNMAPPED_ADDR( instrGrp->virt_pc ) ) {    #ifdef EMBRA_USE_QC64     ECi(ori_op_,SHADOW0,RA, 0); /* Save RA for chaining purpose */

⌨️ 快捷键说明

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