callout.h
9.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
/*
* 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 _ABIN32
ERROR - 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 */