📄 embra.h
字号:
/* * 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. * */#ifndef EMBRA_H#define EMBRA_H#include <sys/cdefs.h>/* From embra - should this be shared? */#include "c_port.h"/* From the shared directory */#include "mips_arch.h"#include "addr_layout.h"#include "cpu_state.h"#include "cpu_interface.h"#include "sim_error.h"/* From simos */#include "syslimits.h"#ifndef _LANGUAGE_ASSEMBLY#include "simmisc.h" #include "machine_params.h"/* ***************************************************************** * A form of PC that allows us to pass information as to whether we * are in the delay slot * ****************************************************************/typedef VA PC_BD;#define IN_BD(_pc) ((_pc) & 0x1)#define CLEAR_BD(_pc) ((_pc) & (~(0x1)))/* Directory Entry. Limits to 30 cpus, but ll/sc is word limited *//* Could expand to 62 cpus with lld MIPS III opcode */typedef uint Dir_Entry;/* **************************************************************** * Virtual quick check status byte * *****************************************************************/typedef enum {MEM_D_EXCLUSIVE = 0x80, MEM_I_EXCLUSIVE = 0xc0, MEM_D_SHARED = 0x01, MEM_I_SHARED = 0x41, MEM_INVALID = 0x00} EmVQCMemState;#define VQC_SHARED(_x)((int)(_x) & 0x00000001)#define VQC_EXCL(_x) ((int)(_x) & 0x00000080 )#define VQC_INST(_x) ((int)(_x) & 0x00000040 )#define VQC_DATA(_x) ((int)(_x) == MEM_D_EXCLUSIVE || (int)(_x) == MEM_D_SHARED)#endif /* _LANGUAGE_ASSEMBLY *//* *********************************************************************** * Still this BACKDOOR vs KSEG1 confusion. * ***********************************************************************/#define IS_BACKDOOR(_addr) (IS_KSEG1(_addr))#if defined(SIM_MIPS32)#define IS_USER(_pc) (!IS_KSEG0(_pc))#else#define IS_USER(_pc) (IS_XKUSEG(_pc))#endif/* Zero offset bits, and add a line */#define ALIGN_IT( _val, _mod ) ( ((unsigned)(_val) & (~((unsigned)_mod-1))) +\(unsigned)_mod )#define HOST_SCACHE_LINE_SIZE (128)/* ******************************************************************* * Memory Address macros. Should in fact be somewhere else (not * embra specific) * ******************************************************************/#define MA_TO_UINT(x) ((uint)(x))#define EMBRA_IS_MEMADDR(_m, x) (IS_VALID_MA((_m), (x)))#define EMBRA_IS_PADDR(_m, x) (IS_VALID_PA((_m), (x)))#ifndef _LANGUAGE_ASSEMBLY/* We may need extra state eventually, but right now, CPUState is sufficient*/typedef CPUState EmbraState;extern EmbraState* EMP; /* allocated in driver.c */typedef struct EmbraParams { int sequential; /* not really a param - for now 1 */ int parallel; /* not really a param - for now 0 */ CPUType emode; /* not really a param - EMBRA_CACHE | EMBRA_PAGE */ int MPinUP; /* never set for cpuNum==1 - yes */ int useETLB; /* boolean - yes */ int useVQC; /* boolean - yes */ int stats; /* boolean - yes */ int inlineQC; /* boolean - yes */ int timeQuantum; /* 1024 */ int periodicAnnInterval; /* 32*1024*1024 */ int statInterval; /* 32*1024*1024 */ int miscCheckInterval; /* 50000 */ int separateMMUs;} EmbraParams;extern EmbraParams embra;/* ********************************************************** * Current EMP and cpu is determined by curEmp, updated * on context switches * ********************************************************* */extern int EmbraCurrentCpuNum(void);#define CURR_CPU (curEmp->myNum)extern EmbraState* curEmp;/* Allocated in driver.c This is NOT shared*/extern int quick_ASID[SIM_MAXCPUS];/* Allocated in simos_interface.c - the number of CPUs in the simulation *//* Here are a whole bunch of defines. All of the registers, and how *//* Embra uses them are here. */#endif /* _LANGUAGE_ASSEMBLY *//* DEFINE what registers simulator will use */#ifndef _LANGUAGE_ASSEMBLYtypedef struct RegNoDummy { char nothing[1];} RegNo;#define REGNUM(_x) ((int)(_x))#endif#ifdef _LANGUAGE_ASSEMBLY/* * this is a work-around around the expansion rules of cpp. */#if defined(_ABIN32) #define REGISTER_NUMBER(_x) $/**/_x#else#define REGISTER_NUMBER2(_dollar,_x) _dollar##_x#define REGISTER_NUMBER(_x) REGISTER_NUMBER2($,_x)#endif#else#define REGISTER_NUMBER(_x) (_x)#endif/* ********************************************************************* * new register map: * ********************************************************************* * 0 zero : * 1 at : shadow * 2 v0 : used to return stuff (tc internal) * 3 v1 : shadow * 4 a0-a3 : parameter passing (tc internal + callout) * 8 t0-t2 : shadow * 11 t3-t6 : tc internal * 15 t7 : shadow * 24 t8-t9 : shadow * s0-s8 : common variables * ********************************************************************//* ********************************************************************* * Simulator working registers * SIM_T1 & SIM_T2 are used by ALU_OPS and L/S generally as * rs == SIM_T2, rt == SIM_T1, rd = SIM_T2 * * BRANCHREG holds either the branch condition or the target address if * its a register indirect jump. Therefore it must be saved on * callouts because if we callout in a delay slot, we don't want to * lose our branch information * * XXX bugnion(fix this. should be a callee saved register) * * SIM_T4 Used for Quick Check and link address in branch and link * instructions * ************************************************************************/#define SIM_T1 REGISTER_NUMBER(REG_T3)#define SIM_T2 REGISTER_NUMBER(REG_T4)#define SIM_T3 unused-register#define SIM_T4 REGISTER_NUMBER(REG_T6)/* ******************************************************************* * Simulator permanent registers. * These registers are used to cache the most frequently accessed * variables from within the translation cache. * All registers are callee saved, therefore do not need to * explicitely saved on callouts. * * VSS_BASE == curEmp == &EMP[CURR_CPU] * QC_REG == curEmp->qc_v, (cache mode only) * MMU_REG == curEmp->mmu: base of relocation array * PC_REG == curEmp->PC (must spill on callouts!) * CLOCK_REG== curEmp->XXX * MMUMASK_REG == 0x7fffffff (page mode only) * * IHIT == number of instructions executed * DHIT == number of references * * *******************************************************************//* common variables: reconstruct after callout * Either have these variables callee saved or recompute them * after returning from the callout */#define VSS_BASE REGISTER_NUMBER(REG_S8)#define QC_REG REGISTER_NUMBER(REG_T1)#define PA_REG QC_REG#define MMU_REG REGISTER_NUMBER(REG_T0)#define MMUMASK_REG REGISTER_NUMBER(REG_V1)/* volatile registers: save to EMP before callout. Restore from EMP * Note that the clock and ihit must be adjusted. * Ideally, these registers are caller saved. */#define CLOCK_REG REGISTER_NUMBER(REG_T7)#define IHIT_REG REGISTER_NUMBER(REG_T8)#define DHIT_REG REGISTER_NUMBER(REG_T9)/* internal registers: save to stack if caller saved * * As non-intuitive as this might seem, PC_REG and curEmp->PC * MUST BE KEPT incoherent, the first walue corresponds * to the start ot the BB while the second one is updated on * callouts !!!! * Note that there is an incentive of having them callee saved. * If we support mid-translation context switches, we must * save the BRANCHREG and the PC_REG in the saveArea. */#define BRANCHREG REGISTER_NUMBER(REG_T5)#define PC_REG REGISTER_NUMBER(REG_S5)#define UNUSED REGISTER_NUMBER(REG_T2)/* shadow registers: save to stack if caller saved * Again, there is an incentive of having them callee * saved. */#define SHADOW0 REGISTER_NUMBER(REG_S0)#define SHADOW1 REGISTER_NUMBER(REG_S1)#define SHADOW2 REGISTER_NUMBER(REG_S2)#define SHADOW3 REGISTER_NUMBER(REG_S3)#define SHADOW4 REGISTER_NUMBER(REG_S4)#define SHADOW5 REGISTER_NUMBER(REG_S6)#define SHADOW6 REGISTER_NUMBER(REG_S7)/* DON'T USE $AT!!! VCODE CAN USE $AT and this * CAN HOSE US BIG TIME. Should fix vcode, but for now * play it safe. XXX -BL *//* #define SHADOW7 REGISTER_NUMBER(REG_AT) */#define REGALLOC_LIST {SHADOW0,SHADOW1,SHADOW2, \ SHADOW3,SHADOW4,SHADOW5, \ SHADOW6,0}#ifdef OBSOLETE/* This is used to hold the old PC, so we can see if we are *//* transfering to code on the same page */#define OLD_PC REGISTER_NUMBER(REG_S3)/* In MP_IN_UP, we store the old PC directly in the state structure, *//* so we use it to provide guarantees on interleaving between *//* processors It holds the threshold which, with CLOCK_REG falls under *//* this value, we context switch*/#define TQUANTUM_REG REGISTER_NUMBER(REG_S3)#endif#endif /* EMBRA_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -