/[gxemul]/upstream/0.3.6/src/cpus/cpu_run.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.6/src/cpus/cpu_run.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show annotations)
Mon Oct 8 16:18:56 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 7639 byte(s)
0.3.6
1 /*
2 * Copyright (C) 2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_run.c,v 1.2 2005/09/18 19:54:14 debug Exp $
29 *
30 * Included from cpu_mips.c, cpu_ppc.c etc. (The reason for this is that
31 * the call to a specific cpu's routine that runs one instruction will
32 * be inlined from here.)
33 *
34 * TODO: Rewrite/cleanup. This is too ugly.
35 */
36
37 #include "console.h"
38 #include "debugger.h"
39
40
41 static int instrs_per_cycle(struct cpu *cpu) {
42 #ifdef CPU_RUN_MIPS
43 return cpu->cd.mips.cpu_type.instrs_per_cycle;
44 #else
45 return 1;
46 #endif
47 }
48
49
50 /*
51 * CPU_RUN():
52 *
53 * Run instructions on all CPUs in this machine, for a "medium duration"
54 * (or until all CPUs have halted).
55 *
56 * Return value is 1 if anything happened, 0 if all CPUs are stopped.
57 */
58 int CPU_RUN(struct emul *emul, struct machine *machine)
59 {
60 struct cpu **cpus = machine->cpus;
61 int ncpus = machine->ncpus;
62 int64_t max_instructions_cached = machine->max_instructions;
63 int64_t max_random_cycles_per_chunk_cached =
64 machine->max_random_cycles_per_chunk;
65 int64_t ncycles_chunk_end;
66 int running, rounds;
67
68 /* The main loop: */
69 running = 1;
70 rounds = 0;
71 while (running || single_step) {
72 ncycles_chunk_end = machine->ncycles + (1 << 17);
73
74 machine->a_few_instrs = machine->a_few_cycles *
75 instrs_per_cycle(cpus[0]);
76
77 /* Do a chunk of cycles: */
78 do {
79 int i, j, te, cpu0instrs, a_few_instrs2;
80
81 running = 0;
82 cpu0instrs = 0;
83
84 /*
85 * Run instructions from each CPU:
86 */
87
88 /* Is any cpu alive? */
89 for (i=0; i<ncpus; i++)
90 if (cpus[i]->running)
91 running = 1;
92
93 if (single_step) {
94 if (single_step == 1) {
95 /*
96 * TODO: (Important!)
97 *
98 * If these are enabled, and focus is
99 * shifted to another machine in the
100 * debugger, then the wrong machine
101 * gets its variables restored!
102 */
103 old_instruction_trace =
104 machine->instruction_trace;
105 old_quiet_mode = quiet_mode;
106 old_show_trace_tree =
107 machine->show_trace_tree;
108 machine->instruction_trace = 1;
109 machine->show_trace_tree = 1;
110 quiet_mode = 0;
111 single_step = 2;
112 }
113
114 for (j=0; j<instrs_per_cycle(cpus[0]); j++) {
115 if (single_step)
116 debugger();
117 for (i=0; i<ncpus; i++)
118 if (cpus[i]->running) {
119 int instrs_run =
120 CPU_RINSTR(emul,
121 cpus[i]);
122 if (i == 0)
123 cpu0instrs +=
124 instrs_run;
125 }
126 }
127 } else if (max_random_cycles_per_chunk_cached > 0) {
128 for (i=0; i<ncpus; i++)
129 if (cpus[i]->running && !single_step) {
130 a_few_instrs2 = machine->
131 a_few_cycles;
132 if (a_few_instrs2 >=
133 max_random_cycles_per_chunk_cached)
134 a_few_instrs2 = max_random_cycles_per_chunk_cached;
135 j = (random() % a_few_instrs2) + 1;
136 j *= instrs_per_cycle(cpus[i]);
137 while (j-- >= 1 && cpus[i]->running) {
138 int instrs_run = CPU_RINSTR(emul, cpus[i]);
139 if (i == 0)
140 cpu0instrs += instrs_run;
141 if (single_step)
142 break;
143 }
144 }
145 } else {
146 /* CPU 0 is special, cpu0instr must be updated. */
147 for (j=0; j<machine->a_few_instrs; ) {
148 int instrs_run;
149 if (!cpus[0]->running || single_step)
150 break;
151 do {
152 instrs_run =
153 CPU_RINSTR(emul, cpus[0]);
154 if (instrs_run == 0 ||
155 single_step) {
156 j = machine->a_few_instrs;
157 break;
158 }
159 } while (instrs_run == 0);
160 j += instrs_run;
161 cpu0instrs += instrs_run;
162 }
163
164 /* CPU 1 and up: */
165 for (i=1; i<ncpus; i++) {
166 a_few_instrs2 = machine->a_few_cycles *
167 instrs_per_cycle(cpus[i]);
168 for (j=0; j<a_few_instrs2; )
169 if (cpus[i]->running) {
170 int instrs_run = 0;
171 while (!instrs_run) {
172 instrs_run = CPU_RINSTR(emul, cpus[i]);
173 if (instrs_run == 0 ||
174 single_step) {
175 j = a_few_instrs2;
176 break;
177 }
178 }
179 j += instrs_run;
180 } else
181 break;
182 }
183 }
184
185 /*
186 * Hardware 'ticks': (clocks, interrupt sources...)
187 *
188 * Here, cpu0instrs is the number of instructions
189 * executed on cpu0. (TODO: don't use cpu 0 for this,
190 * use some kind of "mainbus" instead.) Hardware
191 * ticks are not per instruction, but per cycle,
192 * so we divide by the number of
193 * instructions_per_cycle for cpu0.
194 *
195 * TODO: This doesn't work in a machine with, say,
196 * a mixture of R3000, R4000, and R10000 CPUs, if
197 * there ever was such a thing.
198 *
199 * TODO 2: A small bug occurs if cpu0instrs isn't
200 * evenly divisible by instrs_per_cycle. We then
201 * cause hardware ticks a fraction of a cycle too
202 * often.
203 */
204 i = instrs_per_cycle(cpus[0]);
205 switch (i) {
206 case 1: break;
207 case 2: cpu0instrs >>= 1; break;
208 case 4: cpu0instrs >>= 2; break;
209 default:
210 cpu0instrs /= i;
211 }
212
213 for (te=0; te<machine->n_tick_entries; te++) {
214 machine->ticks_till_next[te] -= cpu0instrs;
215
216 if (machine->ticks_till_next[te] <= 0) {
217 while (machine->ticks_till_next[te]
218 <= 0)
219 machine->ticks_till_next[te] +=
220 machine->
221 ticks_reset_value[te];
222 machine->tick_func[te](cpus[0],
223 machine->tick_extra[te]);
224 }
225 }
226
227 /* Any CPU dead? */
228 for (i=0; i<ncpus; i++) {
229 if (cpus[i]->dead && machine->
230 exit_without_entering_debugger == 0)
231 single_step = 1;
232 }
233
234 machine->ncycles += cpu0instrs;
235 } while (running && (machine->ncycles < ncycles_chunk_end));
236
237 /* If we've done buffered console output,
238 the flush stdout every now and then: */
239 if (machine->ncycles > machine->ncycles_flush + (1<<17)) {
240 console_flush();
241 machine->ncycles_flush = machine->ncycles;
242 }
243
244 if (machine->ncycles > machine->ncycles_show + (1<<25)) {
245 machine->ncycles_since_gettimeofday +=
246 (machine->ncycles - machine->ncycles_show);
247 cpu_show_cycles(machine, 0);
248 machine->ncycles_show = machine->ncycles;
249 }
250
251 if (max_instructions_cached != 0 &&
252 machine->ncycles >= max_instructions_cached)
253 running = 0;
254
255 /* Let's allow other machines to run. */
256 rounds ++;
257 if (rounds > 2)
258 break;
259 }
260
261 return running;
262 }
263

  ViewVC Help
Powered by ViewVC 1.1.26