📄 ms_inst.m4
字号:
/* * 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. * */ /* * ms_inst - All the code for executing instructions for the * R4000 like processor * * Jim Bennett * 1993, 1994, 1995 */#include <stdlib.h>#include <math.h>#include "ms.h"#ifdef MIPSY_MXS#include "cp0.h"#include "simmisc.h"#include "sim_error.h"#include "sim.h"#define EXC_FPE EXC_CODE(15) /* Need for R4000 */#elsetypedef int bool;#endif#define SP_NEAR_ONE 0.999999#define DP_NEAR_ONE 0.9999999999999 /* * CHECKFP handles the exception that all floating point * operations can potentially cause: the coprocessor * unusable exception. */define(CHECKFP, ` if (!FPusable(st)) { int _inum = ip - st->iwin; st->iwin_except [_inum] = GetLastException(st); st->iwin_flags [_inum] |= IWIN_FAULT; CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ' ) /* * LS_EXC - is the common code for handling exceptions in load * and store instructions. */define(LS_EXC, ` {#ifdef MIPSY_MXS CPUState *P = (CPUState *)st->mipsyPtr; RECORD_EXCEPTION(P,$1,E_VEC, st->iwin_addr[inum], P->CP0[C0_TLBHI],P->CP0[C0_CTXT], P->CP0[C0_XCTXT]); st->iwin_except [inum] = GetLastException(st); st->iwin_flags[inum] |= IWIN_FAULT;#endif } ' ) /* * opBRANCH and opCALL define the processing common to branch * and call instructions. The only difference between most of * these instructions is the condition under which the branch * is taken. The first argument to the macro is the condition, * the second is a flag indicating if it's a floating point * branch, and the third is a flag indicating if it's a branch * likely instruction. */define(opBRANCH, ` { int inum, ix; BrTREE *br, *right; WorkDecls; if ($2) { CHECKFP } inum = ip - st->iwin; br = &st->branch_tree [st->iwin_br_node[inum]]; right = &st->branch_tree [br->rchild]; ix = bp_pc_to_index(st->iwin_pc [inum]); if ($1) { st->bp_bits[ix]++; if (st->bp_bits[ix] > BP_MAX_VAL) st->bp_bits[ix] = BP_MAX_VAL; if (PredictTaken (right->condition, $3)) br->resolution = PRUNE_LEFT; else br->resolution = PRUNE_RIGHT; st->iwin_branch_pc [inum] = ip->imm; st->iwin_flags[inum] |= IWIN_TAKENBR; if (br->lchild == -1) { th->pc = ip->imm; th->debugpc = cadr_to_addr (st, th->pc);#ifdef BREAKPOINT if (jmpbrk && (th->pc == jmpbrk)) ms_break (st, &st->iwin[st->iwin_curi], "JMPBRK");#endif } } else { st->bp_bits[ix]--; if (st->bp_bits[ix] < 0) st->bp_bits[ix] = 0; if (PredictTaken (right->condition, $3)) br->resolution = PRUNE_RIGHT; else br->resolution = PRUNE_LEFT; st->iwin_branch_pc [inum] = st->iwin_pc [inum] + (PC_INC*(1+BRANCH_SLOTS)); }#if BRANCH_LATENCY > 1 Add_to_worklist (st, BRANCH_LATENCY, finish_branch, (void *)ip);#else th->stall_branch = 0; UpdateStallFetch (th); prune_branch (st, st->iwin_br_node[inum]);#endif } ')define(opCALL, ` { int inum, ix; BrTREE *br, *right; WorkDecls; inum = ip - st->iwin; br = &st->branch_tree [st->iwin_br_node[inum]]; right = &st->branch_tree [br->rchild]; ix = bp_pc_to_index(st->iwin_pc [inum]); if ($1) { Ireg(ip->r1) = cadr_to_addr (st, th->returnpc); st->bp_bits[ix]++; if (st->bp_bits[ix] > BP_MAX_VAL) st->bp_bits[ix] = BP_MAX_VAL; if (PredictTaken (right->condition, $3)) br->resolution = PRUNE_LEFT; else br->resolution = PRUNE_RIGHT; st->iwin_branch_pc [inum] = ip->imm;#ifdef PROCSTATS push_stats (st, th->pc);#endif if (br->lchild == -1) { th->pc = ip->imm; th->debugpc = cadr_to_addr (st, th->pc);#ifdef BREAKPOINT if (jmpbrk && (th->pc == jmpbrk)) ms_break (st, &st->iwin[st->iwin_curi], "JMPBRK");#endif } } else { st->bp_bits[ix]--; if (st->bp_bits[ix] < 0) st->bp_bits[ix] = 0; if (PredictTaken (right->condition, $3)) br->resolution = PRUNE_RIGHT; else br->resolution = PRUNE_LEFT; st->iwin_branch_pc [inum] = st->iwin_pc [inum] + (PC_INC*(1+BRANCH_SLOTS)); }#if BRANCH_LATENCY > 1 Add_to_worklist (st, BRANCH_LATENCY, finish_call, (void *)ip);#else th->stall_branch = 0; UpdateStallFetch (th); prune_branch (st, st->iwin_br_node[inum]);#endif } ') /* * LoadStats - Common routine in loads for updating statistics * related information. */define(LoadStats, ` if (!st->stall_issue)#if PC_LATENCY > 1 { st->reg_excuse[ip->r1>>1] = ST_PC_DLY; st->new_excuse[ip->r1>>1] = ST_CACHE_LSQ; Add_to_worklist (st, PC_LATENCY, update_excuse, (void *)(ip->r1)); }#else st->reg_excuse[ip->r1>>1] = ST_CACHE_LSQ; st->new_excuse[ip->r1>>1] = ST_NO_EXCUSE;#endif ' )static void clear_fpc_stall(struct s_cpu_state *st, THREAD *th, int inum);static int alls_quiet(struct s_cpu_state *st, INST *ip, int excuse);void opILL (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum = ip - st->iwin;#ifdef MIPSY_MXS CPUState *P = (CPUState *)st->mipsyPtr; RECORD_EXCEPTION(P,EXC_II,E_VEC, P->CP0[C0_BADVADDR], P->CP0[C0_TLBHI],P->CP0[C0_CTXT],P->CP0[C0_XCTXT]); st->iwin_except [inum] = GetLastException(st); st->iwin_flags[inum] |= IWIN_FAULT;#endif CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); }void opJ (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; th->pc = ip->imm;#if BRANCH_LATENCY > 1 Add_to_worklist (st, BRANCH_LATENCY, finish_branch, (void *)ip);#else inum = ip - st->iwin; th->stall_branch = 0; UpdateStallFetch (th); prune_branch (st, st->iwin_br_node[inum]);#endif th->debugpc = cadr_to_addr (st, th->pc);#ifdef BREAKPOINT if (jmpbrk && (th->pc == jmpbrk)) ms_break (st, &st->iwin[st->iwin_curi], "JMPBRK");#endif }void opJAL (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; BrTREE *br; WorkDecls; inum = ip - st->iwin; br = &st->branch_tree [st->iwin_br_node[inum]]; Ireg(ip->r1) = cadr_to_addr (st, th->returnpc); br->resolution = PRUNE_LEFT; st->iwin_branch_pc [inum] = ip->imm;#ifdef PROCSTATS push_stats (st, th->pc);#endif if (br->lchild == -1) { th->pc = ip->imm; th->debugpc = cadr_to_addr (st, th->pc);#ifdef BREAKPOINT if (jmpbrk && (th->pc == jmpbrk)) ms_break (st, &st->iwin[st->iwin_curi], "JMPBRK");#endif }#if BRANCH_LATENCY > 1 Add_to_worklist (st, BRANCH_LATENCY, finish_call, (void *)ip);#else th->stall_branch = 0; UpdateStallFetch (th); prune_branch (st, st->iwin_br_node[inum]);#endif }void opBEQ (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) == Ireg(ip->r3),0,0)void opBNE (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) != Ireg(ip->r3),0,0)void opBLEZ (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) <= 0,0,0)void opBGTZ (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) > 0,0,0)void opBLTZ (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) < 0,0,0)void opBGEZ (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) >= 0,0,0)void opBC1F (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH((Ireg(ip->r2) & CONDBIT) == 0,1,0)void opBC1T (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) & CONDBIT,1,0)void opBEQL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) == Ireg(ip->r3),0, 1)void opBNEL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) != Ireg(ip->r3),0, 1)void opBLEZL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) <= 0,0, 1)void opBGTZL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) > 0,0, 1)void opBLTZL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) < 0,0, 1)void opBGEZL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) >= 0,0, 1)void opBC1FL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH((Ireg(ip->r2) & CONDBIT) == 0,1, 1)void opBC1TL (struct s_cpu_state *st, INST *ip, THREAD *th) opBRANCH(Ireg(ip->r2) & CONDBIT,1, 1)void opBLTZAL (struct s_cpu_state *st, INST *ip, THREAD *th) opCALL(Ireg(ip->r2) < 0,0,0)void opBGEZAL (struct s_cpu_state *st, INST *ip, THREAD *th) opCALL(Ireg(ip->r2) >= 0,0,0)void opBLTZALL (struct s_cpu_state *st, INST *ip, THREAD *th) opCALL(Ireg(ip->r2) < 0,0,1)void opBGEZALL (struct s_cpu_state *st, INST *ip, THREAD *th) opCALL(Ireg(ip->r2) >= 0,0,1)void opADDI (struct s_cpu_state *st, INST *ip, THREAD *th) { Ireg(ip->r1) = Ireg(ip->r2) + ip->imm; }void opADDIU (struct s_cpu_state *st, INST *ip, THREAD *th) { Ureg(ip->r1) = Ureg(ip->r2) + ip->imm; }void opSLTI (struct s_cpu_state *st, INST *ip, THREAD *th) { Ireg(ip->r1) = (Ireg(ip->r2) < ip->imm ? 1 : 0); }void opSLTIU (struct s_cpu_state *st, INST *ip, THREAD *th) { Ireg(ip->r1) = (Ureg(ip->r2) < (unsigned)ip->imm ? 1 : 0); }void opANDI (struct s_cpu_state *st, INST *ip, THREAD *th) { Ireg(ip->r1) = Ireg(ip->r2) & ip->imm; }void opORI (struct s_cpu_state *st, INST *ip, THREAD *th) { Ireg(ip->r1) = Ireg(ip->r2) | ip->imm; }void opXORI (struct s_cpu_state *st, INST *ip, THREAD *th) { Ireg(ip->r1) = Ireg(ip->r2) ^ ip->imm; }void opHCPY (struct s_cpu_state *st, INST *ip, THREAD *th) { if (ip->op == OPHCPYC1) { CHECKFP() } if ((ip->r1 & (~0x01)) != ip->r3) { Dreg(ip->r1) = Dreg(ip->r3); } Ireg(ip->r1) = Ireg(ip->r2); }void opLB (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; inum = ip - st->iwin; if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, 0, LD_INTEGER_B, ip - st->iwin); LoadStats() }void opPREF (struct s_cpu_state *st, INST *ip, THREAD *th) { WorkDecls; ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, 0, PREFETCH, ip - st->iwin); LoadStats() }void opLH (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; inum = ip - st->iwin; if (st->iwin_addr[inum] & 0x1) { LS_EXC(EXC_RADE) } else if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; } if (st->iwin_flags[inum] & IWIN_FAULT) { CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, 0, LD_INTEGER_H, ip - st->iwin); LoadStats() }void opLWL (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum = ip - st->iwin; WorkDecls; if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, ip->r3, LD_UNSIGNED_L, ip - st->iwin); LoadStats() }void opLW (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; inum = ip - st->iwin; if (st->iwin_addr[inum] & 0x3) { #ifdef R3KLOCKSUPPORT extern void *lockCAShackAddr; if ((ip->imm == 1) && (st->iwin_pc[inum] == *(int *) lockCAShackAddr)) { goto out; }#endif LS_EXC(EXC_RADE) } else if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; }#ifdef R3KLOCKSUPPORT out:#endif if (st->iwin_flags[inum] & IWIN_FAULT) { CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, 0, LD_INTEGER_W, ip - st->iwin); LoadStats() }void opLBU (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum = ip - st->iwin; WorkDecls; if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, 0, LD_UNSIGNED_B, ip - st->iwin); LoadStats() }void opLHU (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; inum = ip - st->iwin; if (st->iwin_addr[inum] & 0x1) { LS_EXC(EXC_RADE) } else if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; } if (st->iwin_flags[inum] & IWIN_FAULT) { CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, 0, LD_UNSIGNED_H, ip - st->iwin); LoadStats() }void opLWR (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; WorkDecls; inum = ip - st->iwin; if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r1, ip->r3, LD_UNSIGNED_R, ip - st->iwin); LoadStats() }void opSB (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; inum = ip - st->iwin; if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r3, 0, ST_INTEGER_B, ip - st->iwin); if (st->stall_issue) return;#ifdef BREAKPOINT if (membrk && ((Ireg(ip->r2) + ip->imm) == membrk)) ms_break (st, &st->iwin[st->iwin_curi], "MEMBRK");#endif }void opSH (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; inum = ip - st->iwin; if (st->iwin_addr[inum] & 0x1) { LS_EXC(EXC_WADE) } else if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; } if (st->iwin_flags[inum] & IWIN_FAULT) { CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r3, 0, ST_INTEGER_H, ip - st->iwin); if (st->stall_issue) return;#ifdef BREAKPOINT if (membrk && ((Ireg(ip->r2) + ip->imm) == membrk)) ms_break (st, &st->iwin[st->iwin_curi], "MEMBRK");#endif }void opSWL (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; inum = ip - st->iwin; if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; CheckSquash (st,ip); th->stall_except = 1; UpdateStallFetch (th); return; } ms_lsq (st, Ireg(ip->r2) + ip->imm, ip->r3, 0, ST_INTEGER_L, ip - st->iwin); if (st->stall_issue) return;#ifdef BREAKPOINT if (membrk && ((Ireg(ip->r2) + ip->imm) == membrk)) ms_break (st, &st->iwin[st->iwin_curi], "MEMBRK");#endif }void opSW (struct s_cpu_state *st, INST *ip, THREAD *th) { int inum; inum = ip - st->iwin; if (st->iwin_addr[inum] & 0x3) { LS_EXC(EXC_WADE) } else if (st->iwin_flags[inum] & IWIN_TLBFAULT) { st->iwin_flags[inum] |= IWIN_FAULT; } if (st->iwin_flags[inum] & IWIN_FAULT) { CheckSquash (st,ip);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -