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

📄 opcodes.c

📁 一个用在mips体系结构中的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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.  * *//**************************************************************** * opcodes.c *  * Implementation of each MIPS instruction and declaration of the * table used to decode them. *  * $Author: bosch $ * $Date: 1998/02/10 00:31:48 $ *****************************************************************/#include "simstats.h"#include "opcodes.h"#include "cpu.h"#include "cpu_state.h"#include "sim_error.h"#include "cp0.h"#include "fpu.h"#include "memref.h"#include "cpu_stats.h"#include "hw_events.h"#include "mdmx.h"#ifdef SOLO#  include "solo.h"#endif#define OP(NAME) \Result NAME(Inst instr, CPUState *P)MipsOpcodeDesc mipsSpecOpcodes[];MipsOpcodeDesc mipsBcondOpcodes[];/* * CHECK_64BIT_ALLOWED() - Check to see if 64bit instructions are permitted, *                         if not raise an exception.  */#if defined(SIM_MIPS64)#define CHECK_64BIT_ALLOWED(_p)  \      if ((_p)->is32bitMode && !IS_KERNEL_MODE((_p))) {  \         EXCEPTION((_p), EXC_II);                 \         return FAILURE;                           \      }#else#define CHECK_64BIT_ALLOWED(_p) \      if (1) {                                           \         EXCEPTION((_p), EXC_II);                 \         return FAILURE;                                       \      }#endif#define CURRENT_PC(_cpu) (pePtr[_cpu]->PC)extern Result MipsyReadMem(VA, void *, RefSize, RefFlavor);extern Result MipsyWriteMem(VA, void *, RefSize, RefFlavor);/*  extern Result MipsyWriteByte(VA, byte);   extern Result MipsyWriteHalf(VA, short);   extern Result MipsyWriteWord(VA, uint data, RefFlavor);   extern Result MipsyWriteDouble(VA, uint64, RefFlavor);   */extern int FlashliteWQFull(int);static void   LongMultiply32 (CPUState *, Reg32, Reg32);static void   LongMultiply64 (CPUState *, Reg64, Reg64);static Result Prefetch(CPUState *, VA, uint);static Result CacheOp(CPUState *, uint, VA, PA);extern PA  LLAddrs[MIPSY_MAX_CPUS];extern int numLLactive;/**************************************************************** * M A J O R   O P C O D E S *****************************************************************/OP(specOp) {   uint   specialFunc = FUNC(instr);   return mipsSpecOpcodes[specialFunc].func(instr, P);}OP(bcondOp) {   uint bcondFunc    = RT(instr);   return mipsBcondOpcodes[bcondFunc].func(instr, P);}OP(addiOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   Reg32_s result32  = (Reg32_s)contents_rs + SIGN_EXTEND32(16, immediate);      if (ARITH_OVFL32(result32, (Reg32_s)contents_rs,                     SIGN_EXTEND32(16, immediate))) {      EXCEPTION(P, EXC_OV);      return FAILURE;   }   /* Don't write this value if there was an overflow */   P->R[RT(instr)] = result32;   return SUCCESS;}OP(addiuOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   P->R[RT(instr)] = (Reg32_s)contents_rs + SIGN_EXTEND32(16, immediate);   return SUCCESS;}OP(andiOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   P->R[RT(instr)] = contents_rs & (0x0000ffff & immediate);   return SUCCESS;}OP(beqOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if (contents_rs == P->R[RT(instr)]) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   } else {       P->branchStatus = BranchStatus_nottaken;   }   return SUCCESS;}OP(beqlOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if (contents_rs == P->R[RT(instr)]) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   } else {      /* Skip instruction in delay slot */      P->nPC = P->nPC + 4;     }   return SUCCESS;}OP(bgtzOp){      int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if (!(SIGN_BIT(contents_rs)) && (contents_rs != 0)) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   }  else {       P->branchStatus = BranchStatus_nottaken;   }   return SUCCESS;}OP(bgtzlOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if (!(SIGN_BIT(contents_rs)) && (contents_rs != 0)) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   } else {      /* Skip instruction in delay slot */      P->nPC = P->nPC + 4;     }   return SUCCESS;}OP(blezOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if ((SIGN_BIT(contents_rs) || (contents_rs == 0))) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   }  else {       P->branchStatus = BranchStatus_nottaken;   }   return SUCCESS;}OP(blezlOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if ((SIGN_BIT(contents_rs) || (contents_rs == 0))) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   } else {      /* Skip instruction in delay slot */      P->nPC = P->nPC + 4;     }   return SUCCESS;}OP(bneOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if (contents_rs != P->R[RT(instr)]) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   } else {       P->branchStatus = BranchStatus_nottaken;   }   return SUCCESS;}OP(bnelOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   if (contents_rs != P->R[RT(instr)]) {      P->branchTarget = P->nPC + (SIGN_EXTEND32(18, (immediate << 2)));      P->branchStatus = BranchStatus_taken;   } else {      /* Skip instruction in delay slot */      P->nPC = P->nPC + 4;     }   return SUCCESS;}OP(cacheOp){   int immediate     = IMMED(instr);   /* Be careful with this one. Mipsy's caches are      physically indexed. */   VA   vAddr;   PA   pAddr;   uint tlbFlavor = TLB_READING;   void *bdoorAddr = 0;   Reg_s contents_rs = P->R[RS(instr)];   #ifdef IRIX6_4                  if (!IS_KERNEL_MODE(P)) {                       /*  is unusable only in kernel and or when the cu0 bit is set. */      CauseReg  causeReg;      StatusReg statusReg;      statusReg.ts_data = P->CP0[C0_SR];      if (!statusReg.s32.ts_cu0) {         causeReg.tc_data = P->CP0[C0_CAUSE];         causeReg.s32.tc_ce = 0;         P->CP0[C0_CAUSE] = causeReg.tc_data;         EXCEPTION(P, EXC_CPU);         return FAILURE;      }   }#endif   /* This is a reserved instruction, but I'm allowing it      to be used in user mode. */   vAddr = SIGN_EXTEND(16, immediate) + contents_rs;      if (TranslateVirtual(P, vAddr, &pAddr, &tlbFlavor,&bdoorAddr) != SUCCESS) {      if (P->cpuStatus != cpu_running) {         P->stalledInst = instr;         STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum));      }      return FAILURE;   }   if (CacheOp(P, instr, vAddr, pAddr) != SUCCESS) {      return FAILURE;   }   return SUCCESS;}OP(daddiOp) {   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   Reg64_s result64 = contents_rs + SIGN_EXTEND64(16, immediate);   CHECK_64BIT_ALLOWED(P);   if (ARITH_OVFL64(result64, contents_rs,                    SIGN_EXTEND64(16, immediate))) {      EXCEPTION(P, EXC_OV);      return FAILURE;   }   /* Don't write this value if there was an overflow */   P->R[RT(instr)] = result64;   return SUCCESS;}OP(daddiuOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   CHECK_64BIT_ALLOWED(P);   P->R[RT(instr)] = contents_rs + SIGN_EXTEND64(16,immediate);   return SUCCESS;   }OP(jOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   P->branchTarget = (P->nPC & (Reg32_s)0xf0000000) | (TARGET(instr) << 2);   P->branchStatus = BranchStatus_taken;   return SUCCESS;}OP(jalOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   P->R[REG_RA] = P->nPC + 4;   P->branchTarget = (P->nPC & (Reg32_s)0xf0000000) | (TARGET(instr) << 2);   P->branchStatus = BranchStatus_taken;   return SUCCESS;   }OP(lbOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   byte data;   VA   vAddr;   Reg base = P->R[RS(instr)];      vAddr = SIGN_EXTEND(16, immediate) + base;       if (MipsyReadMem(vAddr, &data, BYTE_SZ, NO_FLAVOR) != SUCCESS) {      if (P->cpuStatus != cpu_running) {         P->stalledInst = instr;         STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum));      }      return FAILURE;   } else {      P->R[RT(instr)]   = SIGN_EXTEND(8, data);      return SUCCESS;   }}OP(lbuOp){    int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   byte data;   VA   vAddr;   Reg base = P->R[RS(instr)];      vAddr = SIGN_EXTEND(16, immediate) + base;      if (MipsyReadMem(vAddr, &data, BYTE_SZ, NO_FLAVOR) != SUCCESS) {      if (P->cpuStatus != cpu_running) {         P->stalledInst = instr;         STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum));      }      return FAILURE;   } else {      P->R[RT(instr)]   = 0x000000ff & data;      return SUCCESS;   }}OP(lhOp){   int immediate     = IMMED(instr);   short data;   VA    vAddr;   Reg   base = P->R[RS(instr)];   Reg_s contents_rs = P->R[RS(instr)];   vAddr = SIGN_EXTEND(16, immediate) + base;      if (vAddr & 0x00000001) {      RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr,                       P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);      /* EXCEPTION(P->myNum,EXC_RADE); */      return FAILURE;   }      if (MipsyReadMem(vAddr, &data, HALF_SZ, NO_FLAVOR) != SUCCESS) {      if (P->cpuStatus != cpu_running) {         P->stalledInst = instr;         STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum));      }      return FAILURE;    } else {      P->R[RT(instr)]   = SIGN_EXTEND(16,data);      return SUCCESS;   }}OP(lhuOp){   int immediate     = IMMED(instr);   Reg_s contents_rs = P->R[RS(instr)];   short data;   VA    vAddr;   Reg   base = P->R[RS(instr)];      vAddr = SIGN_EXTEND(16, immediate) + base;      if (vAddr & 0x00000001) {      RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr,                       P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);      /* EXCEPTION(P->myNum,EXC_RADE); */      return FAILURE;   }      if (MipsyReadMem(vAddr, &data, HALF_SZ, NO_FLAVOR) != SUCCESS) {      if (P->cpuStatus != cpu_running) {         P->stalledInst = instr;         STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum));      }      return FAILURE;   } else {      P->R[RT(instr)]   = 0x0000ffff & data;      return SUCCESS;   }}OP(luiOp){   int immediate     = IMMED(instr);   P->R[RT(instr)] = immediate << 16;   return SUCCESS;}OP(llOp){   int immediate     = IMMED(instr);   Reg32_s data;   VA   vAddr;   Reg base = P->R[RS(instr)];      vAddr = SIGN_EXTEND(16, immediate) + base;      if (vAddr & 0x00000003) {      RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr,                       P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);      /* EXCEPTION(P->myNum,EXC_RADE); */      return FAILURE;   }      if (UNCACHED_LL_SC) {      if (!P->LLbit) {         numLLactive++;      }   }      P->LLbit = 1;    if (MipsyReadMem(vAddr, &data, WORD_SZ, LL_FLAVOR) != SUCCESS) {      if (P->cpuStatus != cpu_running) {         P->stalledInst = instr;         STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum));         STATS_SET(P->myNum, syncStallStart, MipsyReadTime(P->myNum));         if (UNCACHED_LL_SC) {            LLAddrs[P->myNum] = (PA) -1;            if (P->LLbit) {               numLLactive--;             }         }                  P->LLbit = 0;       }      return FAILURE;   } else {      P->R[RT(instr)] = data;      STATS_INC(P->myNum, syncStats.lls, 1);      STATS_ADD_INTERVAL(P->myNum, syncStats.llStallTime, syncStallStart);      if (data & 1)          STATS_INC(P->myNum, syncStats.llNonZero, 1);   }   return SUCCESS;}OP(lldOp){   int immediate     = IMMED(instr);   Reg64  data;   VA   vAddr;   Reg base = P->R[RS(instr)];      CHECK_64BIT_ALLOWED(P);   vAddr = SIGN_EXTEND(16, immediate) + base;      if (vAddr & 0x00000007) {      RECORD_EXCEPTION(P, EXC_RADE, E_VEC, vAddr,                       P->CP0[C0_TLBHI], P->CP0[C0_CTXT], P->CP0[C0_XCTXT]);      return FAILURE;   }      if (UNCACHED_LL_SC) {      if (!P->LLbit) {         numLLactive++;      }   }      P->LLbit = 1;    if (MipsyReadMem(vAddr, &data, DOUBLE_SZ, LL_FLAVOR) != SUCCESS) {      if (P->cpuStatus != cpu_running) {         P->stalledInst = instr;         STATS_SET(P->myNum, stallStart, MipsyReadTime(P->myNum));         STATS_SET(P->myNum, syncStallStart, MipsyReadTime(P->myNum));         if (UNCACHED_LL_SC) {            LLAddrs[P->myNum] = (PA) -1;            if (P->LLbit) {               numLLactive--;             }         }                  P->LLbit = 0;       }      return FAILURE;   } else {      P->R[RT(instr)] = data;      STATS_INC(P->myNum, syncStats.lls, 1);      STATS_ADD_INTERVAL(P->myNum, syncStats.llStallTime, syncStallStart);      if (data & 1)          STATS_INC(P->myNum, syncStats.llNonZero, 1);   }

⌨️ 快捷键说明

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