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

📄 decoder.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees *    of Leland Stanford Junior University. *  * This file is part of the SimOS distribution.  * See LICENSE file for terms of the license.  * *//*************************************************************************** * *  File:           decoder.c * * This decodes a basic block worth of instructions.   * Its main complexity comes in the fact that it * is given a physical PC which, if it runs off the end of a page, it * must find the page on which the block continues by converting the * virtual PC.  Thus we need to know the virtual and physical PC *  * $Author: bosch $ * $Date: 1998/02/10 00:30:24 $ * ***************************************************************************/#include <stdio.h>#include "embra.h"#include "decoder.h"#include "main_run.h"#include "annotations.h"#include "mem_control.h"#include "cp0.h"#include "clock.h"#include "driver.h"/* We are at a page boundary if the lower 12 bits are 0 */#define PAGE_BOUNDARY( val ) (!((val) & (DEFAULT_PAGESZ-1)))#define NOP 0#define MAX_NOPS 12int maxInGroup;voidDecoderInit(void){/* maximum number of instructions in one group *//* It should be relatively large so 1 basic block doesn't have to get *//* artificially chopped up in the TC, but it must be smaller than *//* TQUANT so that you can guarantee interleaving every TQUANT *//* instructions, but you can still execute blocks larger than TQUANT *//* instructions */    maxInGroup = embra.timeQuantum - 1;   if( maxInGroup > INST_GRP_LIMIT )      maxInGroup = INST_GRP_LIMIT;}/*----------------------------------------------------------------------------- * *      Routine:    DecodeInstrs * *      Parameters:  * *      instrGrp - a group of instructions, to fill stuff in.  *       *----------------------------------------------------------------------------*/void DecodeInstrs( InstrGrp* thisGrp, int cpuNum, VA pc, int is_delay_slot_instr ){  unsigned int code;  /* value of binary code read in. */  unsigned int *code_ptr;  int ctl_inst = 0;  int ctl_reg1 = REG_NONE;  int ctl_reg2 = REG_NONE;  int Delayed=0;    /* used as a flag for the delayed slot. */  int i;   /* Translate VA PC into a physical address PC */   /* Note, if the VA PC is a backdoor address, mem_translate jumps to */   /* it directly, and then executes goto_continue_run with the present */   /* return address.  Simulating backdoor code is a bad idea */   /* If we take an exception, we don't return */  thisGrp->phys_pc = mem_translate(cpuNum,pc);  thisGrp->maPC    = PHYS_TO_MEMADDR(M_FROM_CPU(cpuNum),thisGrp->phys_pc );  thisGrp->cpuNum = cpuNum;  thisGrp->virt_pc = pc;  thisGrp->is_delay_slot_instr = is_delay_slot_instr;  thisGrp->next_maPC = 0;  thisGrp->GrpLen = 0;  thisGrp->numDMemoryAcesses = 0;  thisGrp->numIMemoryAcesses = 0;  thisGrp->delay_slot_reg_conflict = 0;  thisGrp->no_reg_allocate = 0;  thisGrp->is_rfe_block = 0;  thisGrp->delay_slot_reg_conflict = 0;#if defined(SIM_MIPS32)  thisGrp->isKseg0 =  IS_KSEG0(thisGrp->virt_pc);#else  thisGrp->isKseg0 =  IS_UNMAPPED_ADDR(thisGrp->virt_pc);#endif  code_ptr = (uint*)thisGrp->maPC;  /* Get a group of instructions, not exceeding maxInGroup number.  */  while (thisGrp->GrpLen < maxInGroup)     {#ifndef DEBUG_TRANSLATOR       VASSERT( EMBRA_IS_MEMADDR( M_FROM_CPU(cpuNum), code_ptr ),                ("\nDecoder code_ptr 0x%x thiGrp 0x%x\n",                 code_ptr, thisGrp) );#endif       code = *code_ptr++;      /* XXX Syscall instructions don't generate signals.  To enable */      /* simos fast mode */       /* to catch syscalls, they are statically translated to the */      /* unaligned load */       if( code == SIMOS_HACKED_SYSCALL )        code = (spec_op<<26) |  syscall_op;      if( code == SIMOS_HACKED_TNS ) {		 code = (mendel_tns<<26);		 thisGrp->no_reg_allocate = 1;	  }      thisGrp->instrs[thisGrp->GrpLen] = code;      thisGrp->pcAnn[thisGrp->GrpLen] = 0;      if (AnnFMLookup(thisGrp->virt_pc+INST_SIZE*thisGrp->GrpLen,ANNFM_PC_TYPE)) {         thisGrp->pcAnn[thisGrp->GrpLen] =ANNFM_PC_TYPE ;         thisGrp->no_reg_allocate = 1;         thisGrp->delay_slot_reg_conflict = 1;      }       if (AnnFMLookup(thisGrp->virt_pc+INST_SIZE*thisGrp->GrpLen,ANNFM_PRE_PC_TYPE)) {         thisGrp->pcAnn[thisGrp->GrpLen] |=ANNFM_PRE_PC_TYPE ;         thisGrp->no_reg_allocate = 1;         thisGrp->delay_slot_reg_conflict = 1;      }           thisGrp->GrpLen++;      /*       * Corner case: the NEXT instruction will be on the next page,       * If this instruction is a control instruction, two things can        * happen: either this is the first instruction of the BB, in        * which case the (branch,DB) straddling pages case ocurs.       * if this is not the case, ie a branch at the end of a        * page that is not the first instruction of the BB, then       * we shorten the BB to exclude the branch. the branch and branch       * delay will be translated separately.        */      if (PAGE_BOUNDARY((unsigned) code_ptr) &&          !IS_KSEG0(thisGrp->virt_pc) &&           IsCtlInstr(code) &&           thisGrp->GrpLen > 1) {         thisGrp->GrpLen--;         break;      }      /* Gather information about the instruction group */      switch( MAJOR_OPCODE( code ) ) {	  case spec_op:		 switch( FUNC( code ) )			{			   /*************************************/			   /* Shifts -- */			   /*************************************/			case sll_op:    /* [rt] shift by shamt -> [rd] */			case sra_op:			case srl_op:			   thisGrp->reg2alloc[rt(code)].num_src++;			   if( Delayed )				  thisGrp->delay_slot_reg_conflict |= 					 ((rd(code)==ctl_reg1) || (rd(code)==ctl_reg2) );			   break;			case syscall_op:			case break_op:                           Delayed = 1;			   break;			case div_op:  /* [rs] op [rt] -> HI & LO */			case divu_op:			case mult_op:			case multu_op:			case ddiv_op:			case ddivu_op:			case dmult_op:			case dmultu_op:			   thisGrp->reg2alloc[rs(code)].num_src++;			   thisGrp->reg2alloc[rt(code)].num_src++;			   break;			case mfhi_op: /* move HI to rd */			case mflo_op: /* move LO to rd */			   /* Is this even allowed? */			   if( Delayed )				  thisGrp->delay_slot_reg_conflict |= 					 ((rd(code)==ctl_reg1) || (rd(code)==ctl_reg2) );			   break;			case mthi_op: /* move rs to HI  */			case mtlo_op: /* move rs to LO */			   thisGrp->reg2alloc[rs(code)].num_src++;			   break;			   /*************************************/			   /* Arithmetic specials */			   /* rs == SIM_T1, rt == SIM_T2, rd == SIM_T2 */			   /*************************************/			   /* [rs] op [rt] -> [rd] */			case add_op:			case addu_op:			case and_op:			case nor_op:			case or_op:			case sllv_op:			case slt_op:			case srav_op:			case sltu_op:			case srlv_op:			case sub_op:			case subu_op:			case xor_op:                        case dadd_op:                        case daddu_op:                        case dsll_op:                        case dsll32_op:                        case dsllv_op:                        case dsrl_op:                        case dsrl32_op:                        case dsrlv_op:                        case dsra_op:                        case dsra32_op:                        case dsrav_op:                        case dsub_op:                        case dsubu_op:			   thisGrp->reg2alloc[rs(code)].num_src++;			   thisGrp->reg2alloc[rt(code)].num_src++;			   if( Delayed )				  thisGrp->delay_slot_reg_conflict |= 					 ((rd(code)==ctl_reg1) || (rd(code)==ctl_reg2) );			   break;                        case movc_op:                        case movz_op:                        case movn_op:			   thisGrp->reg2alloc[rs(code)].num_src++;			   thisGrp->reg2alloc[rt(code)].num_src++;			   if( Delayed )				  thisGrp->delay_slot_reg_conflict |= 					 ((rd(code)==ctl_reg1) || (rd(code)==ctl_reg2) );			   break;                        case tge_op:                        case tgeu_op:                        case tlt_op:                        case tltu_op:                        case teq_op:                        case tne_op:			   thisGrp->reg2alloc[rs(code)].num_src++;			   thisGrp->reg2alloc[rt(code)].num_src++;                           break;			case jr_op:			case jalr_op:			   ctl_inst = 1;			   ctl_reg1 = rs(code)?rs(code):REG_NONE;			   thisGrp->reg2alloc[rs(code)].num_src++;			   break;			}			   break;             	  case bcond_op:		 switch( rt(code) )			{			case bgezal_op:			case bgezall_op:			case bgez_op:			case bgezl_op:			case bltzal_op:			case bltzall_op:			case bltz_op:			case bltzl_op:			   thisGrp->reg2alloc[rs(code)].num_src++;			   ctl_inst = 1;			   ctl_reg1 = rs(code)?rs(code):REG_NONE;			   break;                        case tgei_op:                        case tgeiu_op:                        case tlti_op:                        case tltiu_op:                        case teqi_op:                        case tnei_op:			   thisGrp->reg2alloc[rs(code)].num_src++;                           break;			default:                           CPUWarning("Unknown REGIMM opcode\n");                           ASSERT(0);			}                 break;			   /* NOTE: move to c0 are handled by callout */	  case cop0_op:		 /* Because these functions callout & write the register file */		 /* we have to treat them as contenders for the ctl_instr registers */		 /* This is slightly conservative because one of these functions */		 if( Delayed )			thisGrp->delay_slot_reg_conflict = 1;		 if( IS_CP0_FUNC( code ) )			{			   switch( FUNC( code ) )				  {				  case tlbr_op:				  case tlbwi_op:				  case tlbwr_op:				  case tlbp_op:					 break;                                         				  case eret_op:                                  case rfe_op:                                      /*                                       * Remember that rfe and eret have the same                                      * semantic in SimOS (we don't support the r3k,                                       * and highjack the opcode                                       */                                     Delayed = 1;  /* ERET is non-delayed branch */ 					 thisGrp->is_rfe_block = 1;					 break;				  default:					 break;				  }			}		 else			{              			   /* Operation contained in rs */			   switch( rs( code ) ) {                           case dmfc_op:			   case mfc_op:                              thisGrp->no_reg_allocate = 1;                              /* Destination of mfc, dmtc is RT, not RD (kind of silly)*/                              if( Delayed )                                 thisGrp->delay_slot_reg_conflict |=                                     ((rt(code)==ctl_reg1) || (rt(code)==ctl_reg2) );				  break;                           case dmtc_op:			   case mtc_op:                              thisGrp->no_reg_allocate = 1;                              thisGrp->delay_slot_reg_conflict = 1;                              break;			   default:				  break;			   } 			}				  break;	  case cop1_op:            switch( rs(code) )               {               case mtc_op:               case dmtc_op:               case ctc_op:

⌨️ 快捷键说明

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