📄 callout.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 CALLOUT_H#define CALLOUT_H/* * In order to support 64bit mips we defined symbols for * opcodes depending on the SIM_MIPS32 flag. We have * REG_ST_OP store a register opcode. * REG_LD_OP load a register opcode. * ADDR_ADD_OP add a register to an VA opcode. * ADDR_ADDI_OP add a immediate to a VA opcode. */#ifdef SIM_MIPS32#define VC_REG_ST_OP VC_sw_op_#define VC_REG_LD_OP VC_lw_op_#define REG_ST_OP v_stui#define REG_LD_OP v_ldui#define VC_ADDR_ADD_OP VC_addu_op_#define VC_ADDR_ADDI_OP VC_addiu_op_#else /* Support 64bit so must use ld/sd/daddu ops */#ifndef _ABIN32ERROR - 64bit Embra only currently works on SGIN32#endif#define VC_REG_ST_OP VC_sd_op_#define VC_REG_LD_OP VC_ld_op_#define REG_ST_OP v_stli#define REG_LD_OP v_ldli#define VC_ADDR_ADD_OP VC_daddu_op_#define VC_ADDR_ADDI_OP VC_daddiu_op_#endif /* ifndef SIM_MIPS32 *//* Callout Notes: This file has been rewritten to use vcode to generate the code at run-time. That is why routines are function pointers. Callout trashes temps Callout routines run on simulator stack. See target_table in main_run.c for a list of the function addresses actually stored at these offsets...*/#define CALLOUT_TLBR 1*4#define CALLOUT_TLBWI 2*4#define CALLOUT_TLBWR 3*4#define CALLOUT_TLBP 4*4#define CALLOUT_RFE 5*4#define CALLOUT_ERET 6*4#define CALLOUT_RAISE_C1_UNUSABLE 7*4#define CALLOUT_MTC0 8*4#define CALLOUT_EXCEPTION 9*4#define CALLOUT_TNS 10*4#define CALLOUT_DEBUGER_BREAK 11*4#define CALLOUT_KERN_DEBUGER_BREAK 12*4#define CALLOUT_PC_ANN 13*4#define CALLOUT_GRAB_LOCK 14*4#define CALLOUT_RELEASE_LOCK 15*4#define CALLOUT_UTIL_FUNC 16*4#define CALLOUT_MFC0 17*4#define CALLOUT_PREPC_ANN (18*4)#define CALLOUT_CACHEOP (19*4)#ifndef _LANGUAGE_ASSEMBLY/* Types */typedef void (*vfptr)(); /* Pointer to function returning void *//* Also see translator.h */C_LINK void (*callout)( unsigned, unsigned, unsigned, unsigned );C_LINK void do_periodic_callout( unsigned, unsigned, unsigned, unsigned);C_LINK void embra_sync_barrier(void);C_LINK unsigned MoveToC0_wrapper( unsigned, unsigned, unsigned, unsigned);C_LINK unsigned raise_c1_unusable( unsigned, unsigned, unsigned, unsigned);typedef unsigned (*mr_ptr)(unsigned, int); /* pointer to mem_ref_wrapper */typedef unsigned (*mar_ptr)(unsigned, int, K0A);/* pointer to mem_ref_wrapper */C_LINK unsigned (*mem_ref_wrapper)( unsigned int, int new_state );C_LINK unsigned (*phys_mem_ref_wrapper)( unsigned int, int new_state, K0A );C_LINK unsigned (*pa_mem_ref_wrapper)( unsigned int, int new_state, K0A );#endif /* _LANGUAGE_ASSEMBLY *//* *************************************************************** * Callout stack management * ***************************************************************/#define STOFF_CC_CORR (4*4)#define STOFF_BRANCHREG (6*4)#define STOFF_SHADOW (8*4)#define SHADOW_SIZE (8*8)#define STOFF_RA (STOFF_SHADOW+SHADOW_SIZE)#define STOFF_SIMOS_RA (252)/* ********************************************************************* * Assembly macros used by main_run.s and callout.s * *********************************************************************//* ******************************************************************** * Cycle count correction and IHIT/DHIT counters. * * 2 values of the countdown are saved in the EMP structure, * before and after the adjustment. The former one is * used to determine if we will finish the quantum before * the end of the BB and therefore need to CX. * * Note also that the callout might modify the cycleCountdown and * then return (in the presence of a cache miss) so that we need * to restore the value from the EMP structure. * The same can also be true of IHIT and DHIT depending on how * these are handled. * * ********************************************************************/#define CORRECT_OUTGOING_CC(_corr) \ v_stui(_corr, sp, STOFF_CC_CORR); \ v_stui(clock_reg, vss_base, BCCD_OFF); \ v_addu(clock_reg, clock_reg, _corr); \ v_subu(ihit_reg, ihit_reg, _corr); \ v_stui(clock_reg, vss_base, CCD_OFF); \ v_stui(dhit_reg, vss_base, SDHIT_OFF); \ v_stui(ihit_reg, vss_base, SIHIT_OFF);#define CORRECT_INCOMING_CC \ v_ldui(clock_reg, vss_base, CCD_OFF); \ v_ldui(dhit_reg, vss_base, SDHIT_OFF); \ v_ldui(ihit_reg, vss_base, SIHIT_OFF); \ v_ldui(a3, sp, STOFF_CC_CORR); \ v_subu(clock_reg, clock_reg, a3); \ v_addu(ihit_reg, ihit_reg, a3);/* *********************************************************************** * Some registers have to be saved on the stack only, and restored after * the callout. * * Note that this code is highly dependent on which underlying registers * are used. For example caller saved registers need NOT be saved and * restored. On the other hand, callee saved registers need to be * saved and restored. * * Specifically, we need to * store and restore the volatile registers from EMP (even if callee saved!) * store and restore the shadow registers from the stack * restored only the common variables from EMP * (unless they are callee saved. * ***********************************************************************/#define STACK_SAVE_REGS \ REG_ST_OP(branchreg, sp, STOFF_BRANCHREG); \ v_stui(ra, sp, STOFF_RA);#define STACK_RESTORE_REGS \ REG_LD_OP(branchreg, sp, STOFF_BRANCHREG); \ v_ldui(ra, sp, STOFF_RA); \ v_ldui(qc_reg, vss_base, CACHE_AX_OFF); \ v_ldui(mmumask_reg, vss_base, SSREG2_OFF); \ v_ldui(mmu_reg, vss_base, MMU_OFF);#define LOAD_COMMON_VARS \ v_ldui(qc_reg, vss_base, CACHE_AX_OFF); \ v_ldui(mmumask_reg, vss_base, SSREG2_OFF); \ v_ldui(mmu_reg, vss_base, MMU_OFF);#if defined(SHADOW8)<< -- additional register. >><< -- Please make sure to add these to the macros below >>#endif/* !!! this highly depends on the allocation of registers * SHADOW0,SHADOW1,SHADOW2,SHADOW3 are callee saved --> optimize * Note that this will NOT work if we context switch within * a block. */#define SAVE_SHADOW_REGS \/* REG_ST_OP SHADOW0,STOFF_SHADOW+0*8(sp); */ \/* REG_ST_OP SHADOW1,STOFF_SHADOW+1*8(sp); */ \/* REG_ST_OP SHADOW2,STOFF_SHADOW+2*8(sp); */ \/* REG_ST_OP SHADOW3,STOFF_SHADOW+3*8(sp); */ \/* REG_ST_OP SHADOW4,STOFF_SHADOW+4*8(sp); */ \/* REG_ST_OP SHADOW5,STOFF_SHADOW+5*8(sp); */ \/* REG_ST_OP SHADOW6,STOFF_SHADOW+6*8(sp); */ \/* REG_ST_OP(shadow7, sp, STOFF_SHADOW+7*8); */#define RESTORE_SHADOW_REGS \/* REG_LD_OP SHADOW0,STOFF_SHADOW+0*8(sp); */ \/* REG_LD_OP SHADOW1,STOFF_SHADOW+1*8(sp); */ \/* REG_LD_OP SHADOW2,STOFF_SHADOW+2*8(sp); */ \/* REG_LD_OP SHADOW3,STOFF_SHADOW+3*8(sp); */ \/* REG_LD_OP SHADOW4,STOFF_SHADOW+4*8(sp); */ \/* REG_LD_OP SHADOW5,STOFF_SHADOW+5*8(sp); */ \/* REG_LD_OP SHADOW6,STOFF_SHADOW+6*8(sp); */ \/* REG_LD_OP(shadow7, sp, STOFF_SHADOW+7*8); */#if EMBRA_MPCACHE/* For parallel cache mode *//* These insure that when we are called out of the translation *//*cache, our CPU state reflects this fact *//* Since none of these functions *//* ever waits on a line, setting this bit is only a performance *//* enhancer */ /* This is useful if one cpu hits a breakpoint while the other *//* is executing because we could deadlock if the executing cpu *//* needs to perform an intervention *//* It needs to be set here and in main_run.s as well. *//* It is not necessary for the page mode stubs, because it is used *//*for interventions *//* If VSS_BASE is zero, we are in a lot of trouble */#define OUT_OF_TC v_stui(vss_base, vss_base, OUTTC_OFF);#define ENTERING_TC v_stui(VREGS[0], vss_base, OUTTC_OFF); /* Store information to rewind QC. We need to rewind it because */ /* there is a race condition between when we update our QC, and */ /* when we actually execute the load or store. In the */ /* meantime, the line could have been stolen */#define SAVE_QC_REWIND v_stui(sim_t2, sp, 16*4);#define RESTORE_QC_REWIND v_ldui(sim_t2, sp, 16*4); /* This saves the address of the beginning of the quick check array in the jumpPC field so if we return non-locally we can redo the quick check and continue */#define SAVE_JUMPPC v_movu(t0, ra); v_addu(t0, t0, sim_t2); v_stui(t0, vss_base, JUMPPC_OFF);#else#define OUT_OF_TC #define ENTERING_TC#define SAVE_QC_REWIND#define RESTORE_QC_REWIND#define SAVE_JUMPPC#endif /* *************************************************************** * Management of the FP register file. We use the underlying registers * to cache the register file. Obviously, these need to be * spilled on callouts and restored before use. * * A flag in the CPUState structure tell whether the fp register * file has been loaded. On use (see the translator), we * check this flag and load the file if necessary. On * callouts and context switches, we save the file is the * flag is set and then clear the flag. * * ***************************************************************//* XXX note: this macro is non-reentrant; can only be called once per * generated function */#define SPILL_FP_IF_ENABLED \{ \ spill_fp_label = v_genlabel(); \ v_ldui(t1, vss_base, FPLOADED_OFF); \ v_beqii(t1, 0, spill_fp_label); \ v_stui(zero, vss_base, FPLOADED_OFF);\ v_jalpi(ra,SpillFP); \ v_label(spill_fp_label); \}#endif /* CALLOUT_H */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -