ms_wrklst.h
2.5 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
/*
* 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_wrklst.h - Definitions for the worklist mechanism for
* the simulator.
*
* The worklist mechanism is designed to handle instructions
* take multiple cycles to execute. These instructions are
* handled by locking their destination register, and then
* scheduling their completion for the appropriate cycle.
*
* Most instructions complete in a single cycle, so they
* don't need to use the worklist mechanism.
*
* Jim Bennett
* 1993, 1994
*/
/* Worklist structure */
typedef struct s_wrklst
{
int cycle; /* Cycle when work is due */
void (*f)(void *st, void *a2);
/* Operation to perform then */
void *arg2; /* Argument to function */
struct s_wrklst *next;
} WorkList;
#define STX ((struct s_cpu_state *)st)
#ifdef INLINE
/*
* Define INLINE to get worklist macros, for performance:
*
* WorkDecls
* Add_to_worklist(st, inc, func, arg)
*
* WorkDecls is a declaration of variables used in Add_to_worklist,
* so it should be included in any procedure that uses the
* Add_to_worklist macro. Add_to_worklist adds the given function
* to the work list, to be executed at the cycle specified by
* inc (increment from the current cycle). Arg is an argument
* that is passed to the function as its second argument. The first
* argument of the function is always st.
*/
#define WorkDecls WorkList *wd_w, *wd_wlp; int wd_c
#define Add_to_worklist(st, inc, func, argument2) { \
wd_w = STX->free_head; \
if (wd_w == NULL) { \
fprintf (stderr, "Out of work items!!\n"); \
exit (1); \
} \
STX->free_head = wd_w->next; \
wd_c = STX->work_cycle+(inc); \
wd_wlp = STX->work_tail; \
if (wd_wlp == NULL) { \
wd_w->next = NULL; \
STX->work_head = wd_w; \
STX->work_tail = wd_w; \
} else if (wd_c < wd_wlp->cycle) { \
wd_wlp = STX->work_head; \
if (wd_c < wd_wlp->cycle) { \
wd_w->next = wd_wlp; \
STX->work_head = wd_w; \
} else { \
for (; wd_wlp->next->cycle < wd_c; \
wd_wlp = wd_wlp->next); \
wd_w->next = wd_wlp->next; \
wd_wlp->next = wd_w; \
} \
} else { \
wd_w->next = NULL; \
wd_wlp->next = wd_w; \
STX->work_tail = wd_w; \
} \
wd_w->cycle = wd_c; \
wd_w->f = func; \
wd_w->arg2 = argument2; \
}
#endif