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
|
# Simulator main loop for sparc. -*- C -*-
# Copyright (C) 1999 Cygnus Solutions.
# Syntax:
# /bin/sh mainloop.in command
#
# Command is one of:
#
# init
# support
# extract-{simple,scache,pbb}
# {full,fast}-exec-{simple,scache,pbb}
#
# A target need only provide a "full" version of one of simple,scache,pbb.
# If the target wants it can also provide a fast version of same, or if
# the slow (full featured) version is `simple', then the fast version can be
# one of scache/pbb.
# A target can't provide more than this.
# ??? After a few more ports are done, revisit.
# Will eventually need to machine generate a lot of this.
case "x$1" in
xsupport)
cat <<EOF
static INLINE void
execute (SIM_CPU *current_cpu, SCACHE *sc)
{
ARGBUF *abuf = &sc->argbuf;
IADDR pc = GET_H_PC ();
USI insn = GETIMEMUSI (current_cpu, pc);
int fast_p = STATE_RUN_FAST_P (CPU_STATE (current_cpu));
if (fast_p)
{
const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
@cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
(*id->sem_full) (current_cpu, sc, insn);
}
else
{
const IDESC *id = @cpu@_decode (current_cpu, pc, insn, insn, abuf);
const CGEN_INSN *opcode = id->opcode;
int trace_p = PC_IN_TRACE_RANGE_P (current_cpu, pc);
int profile_p = PC_IN_PROFILE_RANGE_P (current_cpu, pc);
@cpu@_fill_argbuf (current_cpu, abuf, id, pc, fast_p);
@cpu@_fill_argbuf_tp (current_cpu, abuf, trace_p, profile_p);
/* FIXME: call x-before */
if (ARGBUF_PROFILE_P (abuf))
PROFILE_COUNT_INSN (current_cpu, pc, id->num);
/* FIXME: Later make cover macros: PROFILE_INSN_{INIT,FINI}. */
if (PROFILE_MODEL_P (current_cpu)
&& ARGBUF_PROFILE_P (abuf))
@cpu@_model_insn_before (current_cpu, 1 /*first_p*/);
TRACE_INSN_INIT (current_cpu, abuf, 1);
TRACE_INSN (current_cpu, opcode, abuf, pc);
(*id->sem_full) (current_cpu, sc, insn);
/* FIXME: call x-after */
if (PROFILE_MODEL_P (current_cpu)
&& ARGBUF_PROFILE_P (abuf))
{
int cycles;
cycles = (*id->timing->model_fn) (current_cpu, sc);
@cpu@_model_insn_after (current_cpu, 1 /*last_p*/, cycles);
}
TRACE_INSN_FINI (current_cpu, abuf, 1);
}
}
static INLINE void
do_annul (SIM_CPU *current_cpu)
{
IADDR npc = GET_H_NPC ();
/* ??? log profiling data */
/* ??? anything else */
SET_H_PC (npc);
SET_H_NPC (npc + 4);
}
EOF
;;
xinit)
# Nothing needed.
;;
xfull-exec-simple)
# Inputs: current_cpu, sc, FAST_P
# Outputs: none, instruction is fetched and executed
# Recorded PC is updated after every insn.
# ??? Use of `sc' is a bit of a hack as we don't use the scache.
# We do however use ARGBUF so for consistency with the other engine flavours
# sc is used.
cat <<EOF
{
if (GET_H_ANNUL_P ())
{
do_annul (current_cpu);
SET_H_ANNUL_P (0);
}
else
{
execute (current_cpu, sc);
}
}
EOF
;;
*)
echo "Invalid argument to mainloop.in: $1" >&2
exit 1
;;
esac
|