1 ----------------------------------------------------------------------
2 Patch name: Cosimulation support
4 Status: Cosimulation not working yet.
8 The cosimulation feature doesn't work since Bochs 2.0 release (or may be
11 According to my opinion it should be redefined and implemented in totally
12 different way; for example two Bochs simulators compiled with cosimulation
13 could connect through pipe or TCP/IP and run together comparing the arch
14 automatically state or on demand.
15 Let's assume we have dynamic translation support in Bochs, so we could
16 compile it with cosimulation and run two Bochs binaries compiled with
17 dynamic translation and without and compare between them automatically
18 to assure emulation correctness. The same for any other performance feature.
19 This cosimulation approach should reach the same goals but do it in same
22 OK, I assume the patch could be automatically applied to Bochs 2.2.6 release
23 without any conflicts, but do not think it will work or even compile !
24 The patch is more FYI s.t. you will be able to look on some cosimulation
25 implementation during developing a new one ;)
27 And just to be sure ...
28 I marked the patch root in CVS with tag bochs-cosimulation-patch-root
29 so you always could find some Bochs version to apply it ;)
31 Patch was created with:
35 To patch, apply patch to main bochs directory:
36 > patch -p1 < cosim-patch
37 I skipped automatically generated files from this patch to
38 reduce its absolute size.
39 To regenerate configure file:
40 > autoconf configure.in > configure
41 To regenerate lexer.c, parser.c and parser.h
42 > cd bx_debug; rm -f lexer.c parser.c parser.h; make
43 ----------------------------------------------------------------------
45 diff -uBbwNpr bochs-nocosim/bochs.h bochs/bochs.h
46 --- bochs-nocosim/bochs.h 2006-01-25 22:50:48.078125000 +0200
47 +++ bochs/bochs.h 2006-01-20 21:12:03.000000000 +0200
48 @@ -118,6 +118,37 @@ void bx_reset_options (void);
52 +#if ((BX_DEBUGGER == 1) && (BX_NUM_SIMULATORS >= 2))
54 +// =-=-=-=-=-=-=- Redirected to cosimulation debugger -=-=-=-=-=-=-=
55 +#define DEV_vga_mem_read(addr) bx_dbg_ucmem_read(addr)
56 +#define DEV_vga_mem_write(addr, val) bx_dbg_ucmem_write(addr, val)
58 +#define BX_INP(addr, len) bx_dbg_inp(addr, len)
59 +#define BX_OUTP(addr, val, len) bx_dbg_outp(addr, val, len)
60 +#define BX_HRQ (bx_pc_system.HRQ)
61 +#define BX_RAISE_HLDA() bx_dbg_raise_HLDA()
63 +#define BX_INTR bx_pc_system.INTR
64 +#define BX_SET_INTR(b) bx_dbg_set_INTR(b)
66 +# define BX_CPU_C bx_cpu0_c
67 +# define BX_CPU bx_cpu0
68 +# define BX_MEM_C bx_mem0_c
69 +# define BX_MEM bx_mem0
71 +# define BX_CPU_C bx_cpu1_c
72 +# define BX_CPU bx_cpu1
73 +# define BX_MEM_C bx_mem1_c
74 +# define BX_MEM bx_mem1
76 +#define BX_SET_ENABLE_A20(enabled) bx_dbg_async_pin_request(BX_DBG_ASYNC_PENDING_A20, \
78 +#define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20()
79 +#error FIXME: cosim mode not fixed yet
83 // =-=-=-=-=-=-=- Normal optimized use -=-=-=-=-=-=-=-=-=-=-=-=-=-=
84 // some pc_systems functions just redirect to the IO devices so optimize
85 // by eliminating call here
86 @@ -153,6 +184,8 @@ void bx_reset_options (void);
87 #define BX_SET_ENABLE_A20(enabled) bx_pc_system.set_enable_a20(enabled)
88 #define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20()
93 # define A20ADDR(x) ((x) & bx_pc_system.a20_mask)
95 @@ -176,6 +210,21 @@ void bx_reset_options (void);
97 # define BX_DBG_ASYNC_INTR bx_guard.async.irq
98 # define BX_DBG_ASYNC_DMA bx_guard.async.dma
99 +#if (BX_NUM_SIMULATORS > 1)
100 +// for multiple simulators, we always need this info, since we're
101 +// going to replay it.
102 +# define BX_DBG_DMA_REPORT(addr, len, what, val) \
103 + bx_dbg_dma_report(addr, len, what, val)
104 +# define BX_DBG_IAC_REPORT(vector, irq) \
105 + bx_dbg_iac_report(vector, irq)
106 +# define BX_DBG_A20_REPORT(val) \
107 + bx_dbg_a20_report(val)
108 +# define BX_DBG_IO_REPORT(addr, size, op, val) \
109 + bx_dbg_io_report(addr, size, op, val)
110 +# define BX_DBG_UCMEM_REPORT(addr, size, op, val)
112 +// for a single simulator debug environment, we can optimize a little
113 +// by conditionally calling, as per requested.
115 # define BX_DBG_DMA_REPORT(addr, len, what, val) \
116 if (bx_guard.report.dma) bx_dbg_dma_report(addr, len, what, val)
117 @@ -187,6 +236,8 @@ void bx_reset_options (void);
118 if (bx_guard.report.io) bx_dbg_io_report(addr, size, op, val)
119 # define BX_DBG_UCMEM_REPORT(addr, size, op, val) \
120 if (bx_guard.report.ucmem) bx_dbg_ucmem_report(addr, size, op, val)
121 +#endif // #if (BX_NUM_SIMULATORS > 1)
123 #else // #if BX_DEBUGGER
124 // debugger not compiled in, use empty stubs
125 # define BX_DBG_ASYNC_INTR 1
126 diff -uBbwNpr bochs-nocosim/bx_debug/Makefile.in bochs/bx_debug/Makefile.in
127 --- bochs-nocosim/bx_debug/Makefile.in 2006-01-25 22:46:16.062500000 +0200
128 +++ bochs/bx_debug/Makefile.in 2006-01-24 21:03:53.000000000 +0200
129 @@ -56,6 +56,7 @@ YACC = yacc
137 @@ -147,3 +148,17 @@ symbols.o: symbols.@CPP_SUFFIX@ ../bochs
138 ../cpu/xmm.h ../memory/memory.h ../pc_system.h ../plugin.h \
139 ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
140 ../gui/keymap.h ../instrument/stubs/instrument.h
141 +cosim.o: cosim.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
142 + ../bxversion.h ../gui/siminterface.h ../cpu/cpu.h ../cpu/lazy_flags.h \
143 + ../cpu/hostasm.h ../cpu/icache.h ../cpu/apic.h ../cpu/i387.h \
144 + ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \
145 + ../cpu/xmm.h ../memory/memory.h ../pc_system.h ../plugin.h \
146 + ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
147 + ../gui/keymap.h ../instrument/stubs/instrument.h
148 +sim2.o: sim2.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
149 + ../bxversion.h ../gui/siminterface.h ../cpu/cpu.h ../cpu/lazy_flags.h \
150 + ../cpu/hostasm.h ../cpu/icache.h ../cpu/apic.h ../cpu/i387.h \
151 + ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \
152 + ../cpu/xmm.h ../memory/memory.h ../pc_system.h ../plugin.h \
153 + ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
154 + ../gui/keymap.h ../instrument/stubs/instrument.h
155 diff -uBbwNpr bochs-nocosim/bx_debug/cosim.cc bochs/bx_debug/cosim.cc
156 --- bochs-nocosim/bx_debug/cosim.cc 1970-01-01 02:00:00.000000000 +0200
157 +++ bochs/bx_debug/cosim.cc 2006-01-15 19:55:25.000000000 +0200
159 +/////////////////////////////////////////////////////////////////////////
160 +// $Id: patch.cosimulation,v 1.2 2006/01/25 22:30:07 sshwarts Exp $
161 +/////////////////////////////////////////////////////////////////////////
163 +// Copyright (C) 2001 MandrakeSoft S.A.
165 +// MandrakeSoft S.A.
166 +// 43, rue d'Aboukir
167 +// 75002 Paris - France
168 +// http://www.linux-mandrake.com/
169 +// http://www.mandrakesoft.com/
171 +// This library is free software; you can redistribute it and/or
172 +// modify it under the terms of the GNU Lesser General Public
173 +// License as published by the Free Software Foundation; either
174 +// version 2 of the License, or (at your option) any later version.
176 +// This library is distributed in the hope that it will be useful,
177 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
178 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
179 +// Lesser General Public License for more details.
181 +// You should have received a copy of the GNU Lesser General Public
182 +// License along with this library; if not, write to the Free Software
183 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
188 +#if BX_NUM_SIMULATORS >= 2
190 +unsigned bx_dbg_cosimulateN(bx_dbg_icount_t count)
192 + // execute both master & slave for count instructions,
193 + // handling asynchronous events, etc.
194 + // returns 0 = didn't get through all count instructions
195 + // either a guard was hit, or a divergence occurred
196 + // 1 = got through all count instructions
198 + unsigned master, slave;
199 + bx_dbg_icount_t master_icount, slave_icount;
200 + bx_bool bail_out = 0;
203 + bx_bool pre_A20, post_A20;
204 + unsigned async_head;
205 + bx_dbg_icount_t async_icount, curr_icount;
208 + dbg_printf ( "Error: cosimulateN: count=0\n");
212 + bx_guard.guard_for |= BX_DBG_GUARD_ICOUNT; // stop at icount
213 + bx_guard.guard_for &= ~BX_DBG_GUARD_CTRL_C; // ignore Ctrl-C
216 + // take minimum of requested count and maximum count quantum
217 + if (count > bx_debugger.icount_quantum)
218 + bx_guard.icount = bx_debugger.icount_quantum;
220 + bx_guard.icount = count;
222 + // for now, assume...
223 + master = bx_debugger.master;
224 + slave = bx_debugger.slave;
226 + // run master simulator
227 + bx_debugger.master_slave_mode = BX_DBG_MASTER_MODE;
228 + if (bx_guard.interrupt_requested) {
230 + dbg_printf ("ctrlc typed\n");
232 + bx_guard_found[master].guard_found = 0;
233 + bx_guard_found[master].icount = 0;
234 + if (doit) dbg_printf ("requesting run of master for %u\n",
235 + (unsigned) bx_guard.icount);
236 + // save A20 value before master run
237 + pre_A20 = bx_pc_system.get_enable_a20();
239 + BX_MEM(master)->cpu_loop(-1);
240 + post_A20 = bx_pc_system.get_enable_a20(); // A20 after master run
241 + master_icount = bx_guard_found[master].icount;
244 + bx_pc_system.tickn(master_icount);
245 + save_INTR = bx_pc_system.INTR; // value after master run
246 + bx_pc_system.INTR = 0; // in case slave uses directly
247 + // Change A20 for slave run to model what it was at beginning of
248 + // master run, only if it needs to be changed.
249 + if (pre_A20 != post_A20) {
250 + bx_pc_system.set_enable_a20(pre_A20);
251 + if (BX_MEM(slave)->set_A20)
252 + BX_MEM(slave)->set_A20(pre_A20);
255 + // if guard was anything except for icount, we should terminate
256 + // after synchronizing slave to master
257 + if (bx_guard_found[master].guard_found & ~BX_DBG_GUARD_ICOUNT)
260 + // Synchronize slave to master. Account for Ctrl-C's typed during execution of
262 + bx_debugger.master_slave_mode = BX_DBG_SLAVE_MODE;
264 + // run slave for remaining instructions to catch up to master
265 + curr_icount = master_icount - slave_icount;
266 + if (bx_debugger.async_journal.size) {
267 + // If there were asynchronous events which occurred while the
268 + // master was running, have to run the slave up to each of these
269 + // points individually, and force it to take them on exactly the
270 + // same boundaries.
271 + async_head = bx_debugger.async_journal.head;
272 + async_icount = bx_debugger.async_journal.element[async_head].icount;
273 + curr_icount = async_icount; // only run to next async event
276 + async_head = 0; // keep compiler happy
277 + async_icount = 0; // keep compiler happy
280 + bx_guard_found[slave].guard_found = 0;
281 + bx_guard_found[slave].icount = 0;
282 + bx_guard.icount = curr_icount;
285 + // Async event may be before completion of any instructions,
286 + // for example taking of interrupt.
287 + if (doit) dbg_printf ( "requesting run of slave for %u\n",
288 + (unsigned) bx_guard.icount);
289 + if (bx_debugger.fast_forward_mode) {
290 + bx_guard_found[slave].icount = curr_icount;
291 + bx_guard_found[slave].guard_found = BX_DBG_GUARD_ICOUNT;
293 + BX_MEM(slave)->cpu_loop(-1);
296 + slave_icount += bx_guard_found[slave].icount;
297 + if (bx_guard_found[slave].guard_found & ~BX_DBG_GUARD_ICOUNT) {
299 + // If user type Ctrl-C we're done after synchronizing. If not,
300 + // then we have reached a true guard, and it's time to bail.
301 + if (bx_guard_found[slave].guard_found &
302 + ~(BX_DBG_GUARD_ICOUNT | BX_DBG_GUARD_CTRL_C))
305 + if (bx_debugger.async_journal.size) {
306 + // sanity check: slave should be at async point
307 + if (bx_guard_found[slave].icount != async_icount) {
308 + dbg_printf ( "Error: comsimulateN: async: slave not at sync point.\n");
311 + switch (bx_debugger.async_journal.element[async_head].what) {
312 + case BX_DBG_ASYNC_JOURNAL_IAC:
313 + if (!bx_debugger.fast_forward_mode) {
315 + dbg_printf ("slave: forcing interrupt %u\n",
316 + bx_debugger.async_journal.element[async_head].u.iac.val);
318 + BX_MEM(slave)->dbg_force_interrupt(
319 + bx_debugger.async_journal.element[async_head].u.iac.val);
322 + case BX_DBG_ASYNC_JOURNAL_A20:
323 + bx_pc_system.set_enable_a20(
324 + bx_debugger.async_journal.element[async_head].u.a20.val);
325 + if (BX_MEM(slave)->set_A20)
326 + BX_MEM(slave)->set_A20(
327 + bx_debugger.async_journal.element[async_head].u.a20.val);
329 + case BX_DBG_ASYNC_JOURNAL_NMI:
330 + case BX_DBG_ASYNC_JOURNAL_RESET:
332 + dbg_printf ( "Error: cosimulateN: unimplemented async event.\n");
334 + // async event processed, dequeue it
335 + bx_debugger.async_journal.size--;
336 + bx_debugger.async_journal.head++;
338 + } while (slave_icount < master_icount);
340 + bx_pc_system.INTR = save_INTR; // restore INTR to value after master run
342 + // At this point, both simulators should be at the same point. Either
343 + // they have finished executing for the desired count, or at least for
344 + // a time quantum. Check to see if the environments are in sync.
346 + if (!bx_debugger.fast_forward_mode) {
347 + if (bx_debugger.compare_at_sync.iaddr && (iaddr_res = bx_dbg_compare_sim_iaddr())) {
348 + if (iaddr_res == 1)
350 + } else if (bx_debugger.compare_at_sync.cpu && bx_dbg_compare_sim_cpu())
352 + else if (bx_debugger.compare_at_sync.memory && bx_dbg_compare_sim_memory())
357 +#ifdef DEBUGGER_ERROR
358 + extern void DEBUGGER_ERROR(void);
362 + ret = 0; // didn't complete, stopped
365 + count -= master_icount;
366 + // last icount known to be in sync
367 + bx_debugger.last_sync_icount += master_icount;
369 + goto one_time_slice;
370 + ret = 1; // completed OK
373 + bx_guard.guard_for &= ~BX_DBG_GUARD_ICOUNT;
377 +int bx_dbg_compare_sim_iaddr(void)
379 + // returns 0 = same, 1 = different, 2 = false diff
380 + if (BX_CPU(dbg_cpu)->guard_found.laddr != bx_guard_found[1].laddr) {
382 +#ifdef FALSE_DIFF_DETECT
383 + extern int FALSE_DIFF_DETECT();
384 + if (FALSE_DIFF_DETECT())
389 +#if BX_DBG_ICOUNT_SIZE == 32
390 + "*** Iaddr divergence ***: last know synchronized icount was %lu\n",
391 + (unsigned long) bx_debugger.last_sync_icount
392 +#else // BX_DBG_ICOUNT_SIZE == 64
393 + "*** Iaddr divergence ***: last know synchronized icount was %Lu\n",
394 + (unsigned long long) bx_debugger.last_sync_icount
398 +// dbg_printf ( "Divergence: sim[0].laddr=%x, sim[1].laddr=%x\n",
399 +// (unsigned) BX_CPU(dbg_cpu)->guard_found.laddr,
400 +// (unsigned) bx_guard_found[1].laddr);
401 + return(1); // different
406 +bx_bool bx_dbg_compare_sim_cpu(void)
408 + // (mch) Get cpu structures from both simulators
410 + // Compare the structures (except the descriptor parts of the
411 + // segment registers
412 + bx_dbg_cpu_t regs[2];
414 + BX_MEM(0)->dbg_get_cpu(regs + 0);
415 + BX_MEM(1)->dbg_get_cpu(regs + 1);
420 + // (mch) Yes I know these are macros. The would have been
421 + // inner functions if g++ had supported it.
422 +#define TEST_REG(reg, reg_name) \
424 + if (regs[0].reg != regs[1].reg) { \
425 + printf("COSIM ERROR: [%s] %s: 0x%08x %s: 0x%08x\n", reg_name, SIM_NAME0, regs[0].reg, SIM_NAME1_STR, regs[1].reg); \
430 +#define TEST_REG_WARN(reg, reg_name, mask) \
432 + if ((regs[0].reg & mask) != (regs[1].reg & mask)) { \
433 + printf("COSIM WARNING: [%s] %s: 0x%08x %s: 0x%08x\n", reg_name, SIM_NAME0, (regs[0].reg & mask), SIM_NAME1_STR, (regs[1].reg & mask)); \
438 + TEST_REG(eax, "eax");
439 + TEST_REG(ebx, "ebx");
440 + TEST_REG(ecx, "ecx");
441 + TEST_REG(edx, "edx");
442 + TEST_REG(ebp, "ebp");
443 + TEST_REG(esi, "esi");
444 + TEST_REG(edi, "edi");
445 + TEST_REG(esp, "esp");
446 + TEST_REG_WARN(eflags, "eflags & CF", 0x1);
447 +#define EFLAGS_MASK (~((1 << 11) | (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 0)))
448 + regs[0].eflags &= EFLAGS_MASK;
449 + regs[1].eflags &= EFLAGS_MASK;
450 + TEST_REG(eflags, "eflags");
451 + TEST_REG(eip, "eip");
453 +#define TEST_SEG_REG(reg, reg_name) \
455 + if (regs[0].reg.sel != regs[1].reg.sel || regs[0].reg.valid != regs[1].reg.valid) { \
456 + printf("COSIM ERROR: [%s] %s: 0x%04x (%d) %s: 0x%04x (%d)\n", reg_name, SIM_NAME0, regs[0].reg.sel, regs[0].reg.valid, SIM_NAME1_STR, regs[1].reg.sel, regs[1].reg.valid); \
461 + TEST_SEG_REG(cs, "cs");
462 + TEST_SEG_REG(ss, "ss");
463 + TEST_SEG_REG(ds, "ds");
464 + TEST_SEG_REG(es, "es");
465 + TEST_SEG_REG(fs, "fs");
466 + TEST_SEG_REG(gs, "gs");
467 + TEST_SEG_REG(ldtr, "ldtr");
468 + TEST_SEG_REG(tr, "tr");
470 + if (regs[0].gdtr.base != regs[1].gdtr.base || regs[0].gdtr.limit != regs[1].gdtr.limit) {
471 + printf("COSIM ERROR: [gdtr] %s: 0x%08x:0x%04x %s 0x%08x:0x%04x\n",
472 + SIM_NAME0, regs[0].gdtr.base, regs[0].gdtr.limit, SIM_NAME1_STR, regs[1].gdtr.base, regs[1].gdtr.limit);
475 + if (regs[0].idtr.base != regs[1].idtr.base || regs[0].idtr.limit != regs[1].idtr.limit) {
476 + printf("COSIM ERROR: [idtr] %s: 0x%08x:0x%04x %s 0x%08x:0x%04x\n",
477 + SIM_NAME0, regs[0].idtr.base, regs[0].idtr.limit, SIM_NAME1_STR, regs[1].idtr.base, regs[1].idtr.limit);
484 + TEST_REG(cr0, "cr0");
485 + TEST_REG(cr1, "cr1");
486 + TEST_REG(cr2, "cr2");
487 + TEST_REG(cr3, "cr3");
488 + TEST_REG(cr4, "cr4");
490 + if (regs[0].inhibit_mask != regs[1].inhibit_mask) {
491 + printf("COSIM ERROR [inhibit_mask] %s: %d %s: %d\n",
492 + SIM_NAME0, regs[0].inhibit_mask, SIM_NAME1_STR, regs[1].inhibit_mask);
498 +#if BX_DBG_ICOUNT_SIZE == 32
499 + "*** CPU divergence ***: last know synchronized icount was %lu\n",
500 + (unsigned long) bx_debugger.last_sync_icount
501 +#else // BX_DBG_ICOUNT_SIZE == 64
502 + "*** CPU divergence ***: last know synchronized icount was %Lu\n",
503 + (unsigned long long) bx_debugger.last_sync_icount
508 +#if BX_DBG_ICOUNT_SIZE == 32
509 + "=== CPU divergence ===: last know synchronized icount was %lu\n",
510 + (unsigned long) bx_debugger.last_sync_icount
511 +#else // BX_DBG_ICOUNT_SIZE == 64
512 + "=== CPU divergence ===: last know synchronized icount was %Lu\n",
513 + (unsigned long long) bx_debugger.last_sync_icount
516 +#ifdef DEBUGGER_ERROR
517 + extern void DEBUGGER_ERROR(void);
525 +void clear_dirty_bits (void)
527 + int num_pages = bx_options.memory.Osize->get () * 1024 / 4;
528 + for (int i = 0; i < num_pages; i++) {
529 + BX_MEM(0)->dbg_dirty_pages[i] = 0;
530 + BX_MEM(1)->dbg_dirty_pages[i] = 0;
534 +bx_bool always_check_page[128 * 1024 / 4];
536 +void bx_dbg_always_check(Bit32u page_start, bx_bool on)
538 + always_check_page[page_start / (4 * 1024)] = on;
539 + printf("Forced check on page %08x %s\n",
540 + page_start, on ? "enabled" : "disabled");
543 +bx_bool bx_dbg_compare_sim_memory(void)
546 + int num_pages = bx_options.memory.Osize->get () * 1024 / 4;
548 + for (int i = 0; i < num_pages; i++) {
549 + bx_bool sim0_dirty = BX_MEM(0)->dbg_dirty_pages[i];
550 + bx_bool sim1_dirty = BX_MEM(1)->dbg_dirty_pages[i];
551 + Bit32u page_start = i * 1024 * 4;
553 + if ((sim0_dirty != sim1_dirty) || sim0_dirty || always_check_page[i]) {
554 + // Page has been written, compare
555 + // (mch) I'm quite aware of how hackish this is. I don't care.
556 + extern Bit8u* SIM1_GET_PHYS_PTR(Bit32u page_start);
557 + Bit8u* sim0_page_vec = bx_mem0.vector + page_start;
558 + Bit8u* sim1_page_vec = SIM1_GET_PHYS_PTR(page_start);
560 + if (memcmp(sim0_page_vec, sim1_page_vec, 1024 * 4)) {
561 + printf("COSIM ERROR Physical page %08x differs in content\n", page_start);
562 + for (int j = 0; j < 1024 * 4; j++) {
563 + if (sim0_page_vec[j] != sim1_page_vec[j]) {
564 + printf("%08x %s: %02x %s: %02x\n",
565 + page_start+j, SIM_NAME0, sim0_page_vec[j], SIM_NAME1_STR, sim1_page_vec[j]);
575 +#if BX_DBG_ICOUNT_SIZE == 32
576 + "*** Memory divergence ***: last know synchronized icount was %lu\n",
577 + (unsigned long) bx_debugger.last_sync_icount
578 +#else // BX_DBG_ICOUNT_SIZE == 64
579 + "*** Memory divergence ***: last know synchronized icount was %Lu\n",
580 + (unsigned long long) bx_debugger.last_sync_icount
585 + clear_dirty_bits();
590 +void bx_dbg_journal_a20_event(unsigned val)
592 + unsigned tail, master;
594 + if (bx_debugger.master_slave_mode == BX_DBG_SLAVE_MODE ) {
595 + dbg_printf ( "Error: a20_report: in slave mode.\n");
599 + // Master simulator mode
600 + if (bx_debugger.async_journal.size >= BX_DBG_ASYNC_JOURNAL_SIZE) {
601 + dbg_printf ( "Error: async journal full.\n");
605 + if (bx_debugger.async_journal.size == 0) {
606 + // start off point head & tail at same element
607 + bx_debugger.async_journal.head = 0;
608 + tail = bx_debugger.async_journal.tail = 0;
611 + tail = bx_debugger.async_journal.tail + 1;
613 + if (tail >= BX_DBG_ASYNC_JOURNAL_SIZE) {
614 + dbg_printf ( "Error: a20_report: journal wrapped.\n");
618 + master = bx_debugger.master;
619 + bx_debugger.async_journal.element[tail].what = BX_DBG_ASYNC_JOURNAL_A20;
620 + bx_debugger.async_journal.element[tail].icount = bx_guard_found[master].icount;
621 + bx_debugger.async_journal.element[tail].u.a20.val = val;
623 + if (bx_debugger.async_journal.size)
624 + bx_debugger.async_journal.tail++;
625 + bx_debugger.async_journal.size++;
628 +Bit8u bx_dbg_ucmem_read(Bit32u addr)
631 + unsigned head, tail;
633 + if ( bx_debugger.master_slave_mode == BX_DBG_MASTER_MODE ) {
634 + if (!bx_debugger.fast_forward_mode) {
635 + if (bx_debugger.UCmem_journal.size >= BX_DBG_UCMEM_JOURNAL_SIZE) {
636 + dbg_printf ( "dbg_ucmem_read: journal full.\n");
640 + if (bx_debugger.UCmem_journal.size == 0) {
641 + // start off point head & tail at same element
642 + bx_debugger.UCmem_journal.head = 0;
643 + tail = bx_debugger.UCmem_journal.tail = 0;
646 + tail = bx_debugger.UCmem_journal.tail + 1;
648 + if (tail >= BX_DBG_UCMEM_JOURNAL_SIZE) {
649 + dbg_printf ( "dbg_ucmem_read: journal wrapped.\n");
653 + value = DEV_vga_mem_read(addr);
654 + bx_dbg_ucmem_report(addr, 1, BX_READ, value);
655 + bx_debugger.UCmem_journal.element[tail].op = BX_READ;
656 + bx_debugger.UCmem_journal.element[tail].len = 1;
657 + bx_debugger.UCmem_journal.element[tail].addr = addr;
658 + bx_debugger.UCmem_journal.element[tail].value = value;
659 + if (bx_debugger.UCmem_journal.size)
660 + bx_debugger.UCmem_journal.tail++;
661 + bx_debugger.UCmem_journal.size++;
664 + dbg_printf ( "MASTER UCR: head:%u tail%u size:%u\n",
665 + bx_debugger.UCmem_journal.head,
666 + bx_debugger.UCmem_journal.tail,
667 + bx_debugger.UCmem_journal.size);
671 + value = DEV_vga_mem_read(addr);
676 + if (bx_debugger.UCmem_journal.size == 0) {
677 + dbg_printf ( "Error: ucmem_read: journal empty.\n");
680 + head = bx_debugger.UCmem_journal.head;
681 + value = bx_debugger.UCmem_journal.element[head].value;
683 + if ((bx_debugger.UCmem_journal.element[head].op != BX_READ) ||
684 + (bx_debugger.UCmem_journal.element[head].len != 1) ||
685 + (bx_debugger.UCmem_journal.element[head].addr != addr))
687 + dbg_printf ( "Error: ucmem_read: out of sync with journal.\n");
688 + dbg_printf ( "Error: master: op=%1s len=%u addr=0x%x val=0x%x\n",
689 + (bx_debugger.UCmem_journal.element[head].op==BX_READ) ? "W" : "R",
690 + (unsigned) bx_debugger.UCmem_journal.element[head].len,
691 + (unsigned) bx_debugger.UCmem_journal.element[head].addr,
692 + (unsigned) bx_debugger.UCmem_journal.element[head].value);
693 + dbg_printf ( "Error: slave: op=W len=%u addr=0x%x val=0x%x\n",
694 + (unsigned) 1, (unsigned) addr, (unsigned) value);
697 + // slave UCmem op in sync with journaled master op, delete this entry
698 + bx_debugger.UCmem_journal.head++;
699 + bx_debugger.UCmem_journal.size--;
704 +void bx_dbg_ucmem_write(Bit32u addr, Bit8u value)
706 + unsigned tail, head;
708 + if ( bx_debugger.master_slave_mode == BX_DBG_MASTER_MODE ) {
709 + if (!bx_debugger.fast_forward_mode) {
710 + if (bx_debugger.UCmem_journal.size >= BX_DBG_UCMEM_JOURNAL_SIZE) {
711 + dbg_printf ( "dbg_ucmem_write: journal full.\n");
715 + if (bx_debugger.UCmem_journal.size == 0) {
716 + // start off point head & tail at same element
717 + bx_debugger.UCmem_journal.head = 0;
718 + tail = bx_debugger.UCmem_journal.tail = 0;
721 + tail = bx_debugger.UCmem_journal.tail + 1;
723 + if (tail >= BX_DBG_UCMEM_JOURNAL_SIZE) {
724 + dbg_printf ( "dbg_ucmem_write: journal wrapped.\n");
728 + bx_debugger.UCmem_journal.element[tail].op = BX_WRITE;
729 + bx_debugger.UCmem_journal.element[tail].len = 1;
730 + bx_debugger.UCmem_journal.element[tail].addr = addr;
731 + bx_debugger.UCmem_journal.element[tail].value = value;
733 + if (bx_debugger.UCmem_journal.size)
734 + bx_debugger.UCmem_journal.tail++;
735 + bx_debugger.UCmem_journal.size++;
736 + DEV_vga_mem_write(addr, value);
737 + bx_dbg_ucmem_report(addr, 1, BX_WRITE, value);
739 + DEV_vga_mem_write(addr, value);
743 + if (bx_debugger.UCmem_journal.size == 0) {
744 + dbg_printf ( "Error: ucmem_write: journal empty.\n");
747 + head = bx_debugger.UCmem_journal.head;
749 + if ((bx_debugger.UCmem_journal.element[head].op != BX_WRITE) ||
750 + (bx_debugger.UCmem_journal.element[head].len != 1) ||
751 + (bx_debugger.UCmem_journal.element[head].addr != addr) ||
752 + (bx_debugger.UCmem_journal.element[head].value != value) )
754 + dbg_printf ( "Error: ucmem_write: out of sync with journal.\n");
755 + dbg_printf ( "Error: master: op=%1s len=%u addr=0x%x val=0x%x\n",
756 + (bx_debugger.UCmem_journal.element[head].op==BX_WRITE) ? "W" : "R",
757 + (unsigned) bx_debugger.UCmem_journal.element[head].len,
758 + (unsigned) bx_debugger.UCmem_journal.element[head].addr,
759 + (unsigned) bx_debugger.UCmem_journal.element[head].value);
760 + dbg_printf ( "Error: slave: op=W len=%u addr=0x%x val=0x%x\n",
761 + (unsigned) 1, (unsigned) addr, (unsigned) value);
764 + // slave UCmem op in sync with journaled master op, delete this entry
765 + bx_debugger.UCmem_journal.head++;
766 + bx_debugger.UCmem_journal.size--;
770 +void bx_dbg_async_pin_request(unsigned what, bx_bool val)
772 + // Request from IO devices for change in pin external to CPU.
773 + // This is pended until CPU ack's with bx_dbg_async_pin_ack().
775 + if (bx_debugger.master_slave_mode != BX_DBG_MASTER_MODE) {
776 + dbg_printf ( "Error: dbg_async_pin_request not in master mode.\n");
781 + case BX_DBG_ASYNC_PENDING_A20:
782 + // Q pending status
783 + bx_guard.async_changes_pending.which |= BX_DBG_ASYNC_PENDING_A20;
784 + bx_guard.async_changes_pending.a20 = val;
787 + case BX_DBG_ASYNC_PENDING_RESET:
788 + case BX_DBG_ASYNC_PENDING_NMI:
790 + dbg_printf ( "Error: set_async_pin: unhandled case.\n");
796 +void bx_dbg_async_pin_ack(unsigned what, bx_bool val)
798 + // Acknowledgement from master simulator for pending change in pin
799 + // external to CPU.
801 + if (bx_debugger.master_slave_mode != BX_DBG_MASTER_MODE) {
802 + dbg_printf ( "Error: dbg_async_pin_ack: not master mode.\n");
807 + case BX_DBG_ASYNC_PENDING_A20:
808 + // get rid of pending status
809 + bx_guard.async_changes_pending.which &= ~BX_DBG_ASYNC_PENDING_A20;
810 + // notify pc_system of change
811 + bx_pc_system.set_enable_a20(val);
812 + if (BX_CPU(bx_debugger.master)->set_A20)
813 + BX_CPU(bx_debugger.master)->set_A20(val);
814 + bx_dbg_journal_a20_event(val);
817 + case BX_DBG_ASYNC_PENDING_RESET:
818 + case BX_DBG_ASYNC_PENDING_NMI:
820 + dbg_printf ( "Error: set_async_pin: unhandled case.\n");
825 +Bit32u bx_dbg_inp(Bit16u addr, unsigned len)
828 + unsigned tail, head;
830 + if ( bx_debugger.master_slave_mode == BX_DBG_MASTER_MODE ) {
831 + if (!bx_debugger.fast_forward_mode) {
832 + if (bx_debugger.IO_journal.size >= BX_DBG_IO_JOURNAL_SIZE) {
833 + dbg_printf ( "dbg_inp: journal full.\n");
837 + if (bx_debugger.IO_journal.size == 0) {
838 + // start off point head & tail at same element
839 + bx_debugger.IO_journal.head = 0;
840 + tail = bx_debugger.IO_journal.tail = 0;
843 + tail = bx_debugger.IO_journal.tail + 1;
845 + if (tail >= BX_DBG_IO_JOURNAL_SIZE) {
846 + dbg_printf ( "dbg_inp: journal wrapped.\n");
850 + value = bx_pc_system.inp(addr, len);
851 + bx_debugger.IO_journal.element[tail].op = BX_READ;
852 + bx_debugger.IO_journal.element[tail].len = (Bit8u) len;
853 + bx_debugger.IO_journal.element[tail].addr = addr;
854 + bx_debugger.IO_journal.element[tail].value = value;
855 + if (bx_debugger.IO_journal.size)
856 + bx_debugger.IO_journal.tail++;
857 + bx_debugger.IO_journal.size++;
858 +//dbg_printf ( "MASTER IN: head:%u tail%u size:%u\n",
859 +// bx_debugger.IO_journal.head,
860 +// bx_debugger.IO_journal.tail,
861 +// bx_debugger.IO_journal.size);
864 + value = bx_pc_system.inp(addr, len);
869 + if (bx_debugger.IO_journal.size == 0) {
870 + dbg_printf ( "Error: dbg_inp: journal empty.\n");
871 + return(0xffffffff);
873 + head = bx_debugger.IO_journal.head;
874 + value = bx_debugger.IO_journal.element[head].value;
876 + if ((bx_debugger.IO_journal.element[head].op != BX_READ) ||
877 + (bx_debugger.IO_journal.element[head].len != len) ||
878 + (bx_debugger.IO_journal.element[head].addr != addr) ) {
879 + dbg_printf ( "Error: dbg_inp: out of sync with journal.\n");
880 + dbg_printf ( "Error: master: op=%3s len=%u addr=0x%x\n",
881 + (bx_debugger.IO_journal.element[head].op==BX_WRITE) ? "OUT" : "IN",
882 + (unsigned) bx_debugger.IO_journal.element[head].len,
883 + (unsigned) bx_debugger.IO_journal.element[head].addr);
884 + dbg_printf ( "Error: slave: op=OUT len=%u addr=0x%x\n",
885 + (unsigned) len, (unsigned) addr);
886 + return(0xffffffff);
888 + // slave IO op in sync with journaled master op, delete this entry
889 + bx_debugger.IO_journal.head++;
890 + bx_debugger.IO_journal.size--;
891 +// dbg_printf ( "SLAVE IN: head:%u tail%u size:%u\n",
892 +// bx_debugger.IO_journal.head,
893 +// bx_debugger.IO_journal.tail,
894 +// bx_debugger.IO_journal.size);
899 +void bx_dbg_outp(Bit16u addr, Bit32u value, unsigned len)
901 + unsigned tail, head;
903 + if ( bx_debugger.master_slave_mode == BX_DBG_MASTER_MODE ) {
904 + if (!bx_debugger.fast_forward_mode) {
905 + if (bx_debugger.IO_journal.size >= BX_DBG_IO_JOURNAL_SIZE) {
906 + dbg_printf ( "dbg_outp: IO journal full.\n");
910 + if (bx_debugger.IO_journal.size == 0) {
911 + // start off point head & tail at same element
912 + bx_debugger.IO_journal.head = 0;
913 + tail = bx_debugger.IO_journal.tail = 0;
916 + tail = bx_debugger.IO_journal.tail + 1;
918 + if (tail >= BX_DBG_IO_JOURNAL_SIZE) {
919 + dbg_printf ( "dbg_outp: IO journal wrapped.\n");
923 + bx_debugger.IO_journal.element[tail].op = BX_WRITE;
924 + bx_debugger.IO_journal.element[tail].len = (Bit8u) len;
925 + bx_debugger.IO_journal.element[tail].addr = addr;
926 + bx_debugger.IO_journal.element[tail].value = value;
927 + if (bx_debugger.IO_journal.size)
928 + bx_debugger.IO_journal.tail++;
929 + bx_debugger.IO_journal.size++;
930 + bx_pc_system.outp(addr, value, len);
932 + dbg_printf ( "master: IO journal size now %u\n", bx_debugger.IO_journal.size);
934 + bx_pc_system.outp(addr, value, len);
938 + if (bx_debugger.IO_journal.size == 0) {
939 + dbg_printf ( "Error: dbg_outp: journal empty.\n");
942 + head = bx_debugger.IO_journal.head;
944 + if ((bx_debugger.IO_journal.element[head].op != BX_WRITE) ||
945 + (bx_debugger.IO_journal.element[head].len != len) ||
946 + (bx_debugger.IO_journal.element[head].addr != addr) ||
947 + (bx_debugger.IO_journal.element[head].value != value) ) {
948 + dbg_printf ( "Error: dbg_outp: out of sync with journal.\n");
949 + dbg_printf ( "Error: master: op=%3s len=%u addr=0x%x val=0x%x\n",
950 + (bx_debugger.IO_journal.element[head].op==BX_WRITE) ? "OUT" : "IN",
951 + (unsigned) bx_debugger.IO_journal.element[head].len,
952 + (unsigned) bx_debugger.IO_journal.element[head].addr,
953 + (unsigned) bx_debugger.IO_journal.element[head].value);
954 + dbg_printf ( "Error: slave: op=OUT len=%u addr=0x%x val=0x%x\n",
955 + (unsigned) len, (unsigned) addr, (unsigned) value);
958 + // slave IO op in sync with journaled master op, delete this entry
959 + bx_debugger.IO_journal.head++;
960 + bx_debugger.IO_journal.size--;
962 + dbg_printf ( "slave: IO journal size now %u\n", bx_debugger.IO_journal.size);
966 +void bx_dbg_raise_HLDA(void)
968 + dbg_printf ( "dbg_HLDA called\n");
972 +Bit8u bx_dbg_IAC(void)
974 + // Convience routine. bochs skips this, and calls the PIC code
975 + // directly. This is for other simulators to interface to the
979 + iac = BX_PIC_AIC ();
983 +void bx_dbg_set_INTR(bx_bool b)
985 + if ( bx_debugger.master_slave_mode == BX_DBG_SLAVE_MODE ) {
986 + dbg_printf ( "Error: set_INTR in slave mode.\n");
990 + bx_pc_system.INTR = b;
991 + BX_CPU(bx_debugger.master)->set_INTR(b);
996 +void bx_dbg_diff_memory(void)
998 +#if BX_NUM_SIMULATORS < 2
999 + printf("diff-memory supported only in cosimulation mode\n");
1001 + int num_pages = bx_options.memory.Osize->get () * 1024 / 4;
1002 + for (int i = 0; i < num_pages; i++) {
1003 + BX_CPU(dbg_cpu)->dbg_dirty_pages[i] = 1;
1005 + if (bx_dbg_compare_sim_memory())
1006 + printf("[diff-memory] Diff detected\n");
1008 + printf("[diff-memory] No diff detected\n");
1009 +#endif /* NUM_SIMULATORS < 2 */
1012 +void bx_dbg_sync_memory(bx_bool set)
1014 +#if BX_NUM_SIMULATORS < 2
1015 + printf("sync-memory supported only in cosimulation mode\n");
1017 + bx_debugger.compare_at_sync.memory = set;
1018 + printf("Memory sync %s\n", (set) ? "enabled" : "disabled");
1022 +void bx_dbg_sync_cpu(bx_bool set)
1024 +#if BX_NUM_SIMULATORS < 2
1025 + printf("sync-cpu supported only in cosimulation mode\n");
1027 + bx_debugger.compare_at_sync.cpu = set;
1028 + printf("Register file sync %s\n", (set) ? "enabled" : "disabled");
1032 +void bx_dbg_fast_forward(Bit32u num)
1034 +#if BX_NUM_SIMULATORS < 2
1035 + printf("fast-forward supported only in cosimulation mode\n");
1037 + printf("Entering fast-forward mode\n");
1039 + // Bit32u save_icount_quantum = bx_debugger.icount_quantum;
1040 + // bx_debugger.icount_quantum = num;
1042 + bx_guard.interrupt_requested = 0;
1044 + bx_debugger.fast_forward_mode = 1;
1045 + for (Bit32u e = 0; e < num; e += bx_debugger.icount_quantum)
1046 + if (!bx_dbg_cosimulateN(bx_debugger.icount_quantum))
1048 + bx_debugger.fast_forward_mode = 0;
1049 + // bx_debugger.icount_quantum = save_icount_quantum;
1051 + DEV_vga_refresh();
1053 + printf("Copying CPU...\n");
1055 + if (!BX_CPU(0)->dbg_get_cpu(&cpu) || !BX_CPU(1)->dbg_set_cpu(&cpu))
1056 + printf("Error copying CPU data!\n");
1058 + printf("Copying memory...\n");
1059 + int num_pages = bx_options.memory.Osize->get () * 1024 / 4;
1060 + for (int i = 0; i < num_pages; i++) {
1061 + if (BX_CPU(0)->dbg_dirty_pages[i]) {
1062 + Bit32u page_start = i * 1024 * 4;
1063 + printf("Copying page %08x\n", page_start);
1064 + extern Bit8u* SIM1_GET_PHYS_PTR(Bit32u page_start);
1065 + Bit8u* sim0_page_vec = bx_mem0.vector + page_start;
1066 + Bit8u* sim1_page_vec = SIM1_GET_PHYS_PTR(page_start);
1067 + memcpy(sim1_page_vec, sim0_page_vec, 1024 * 4);
1071 + printf("Taking async events...\n");
1073 + printf("Exiting fast-forward mode\n");
1077 +extern Bit32u conv_4xBit8u_to_Bit32u(const Bit8u* buf);
1080 + (mch) Print various info for logical address.
1082 +void bx_dbg_info_address(Bit32u seg_reg_num, Bit32u offset)
1084 +#if BX_NUM_SIMULATORS < 2
1085 + printf("addr-info only supported in cosim configuration.\n");
1087 + for (int sim = 0; sim < 2; sim++)
1089 + /* Find page table base address */
1090 + bx_dbg_cpu_t regs;
1091 + BX_CPU(sim)->dbg_get_cpu(®s);
1092 + Bit32u base = regs.cr3 & ~0xfff;
1095 + Bit32u directory_addr = base + (offset >> 22) * 4;
1097 + if (BX_CPU(sim)->mem->dbg_fetch_mem(directory_addr, 4, buf)) {
1098 + directory = conv_4xBit8u_to_Bit32u(buf);
1099 + Bit32u table_addr = (directory & ~0xfff) + ((offset >> 12) & 0x3ff) * 4;
1102 + printf("[%s] ", SIM_NAME(sim));
1103 + printf("PDE: %08x (", directory);
1104 + printf("%s, %s, %s, %s, %s)",
1105 + (directory & 1) ? "Present" : "Not present",
1106 + (directory & 2) ? "Read/Write" : "Read-only",
1107 + (directory & 4) ? "User" : "Supervisor",
1108 + (directory & (1 << 5)) ? "Accessed" : "-",
1109 + (directory & (1 << 6)) ? "Dirty" : "-");
1111 + if (directory & 1) {
1112 + if (BX_CPU(sim)->mem->dbg_fetch_mem(table_addr, 4, buf)) {
1113 + table = conv_4xBit8u_to_Bit32u(buf);
1115 + printf(", PTE: %08x (", table);
1116 + printf("%s, %s, %s, %s, %s)\n",
1117 + (table & 1) ? "Present" : "Not present",
1118 + (table & 2) ? "Read/Write" : "Read-only",
1119 + (table & 4) ? "User" : "Supervisor",
1120 + (table & (1 << 5)) ? "Accessed" : "-",
1121 + (table & (1 << 6)) ? "Dirty" : "-");
1123 + printf("[%s] Could not read from physical address %08x\n",
1124 + SIM_NAME(sim), directory_addr);
1131 + printf("[%s] Could not read from physical address %08x\n",
1132 + SIM_NAME(sim), directory_addr);
1138 diff -uBbwNpr bochs-nocosim/bx_debug/dbg_main.cc bochs/bx_debug/dbg_main.cc
1139 --- bochs-nocosim/bx_debug/dbg_main.cc 2006-01-25 22:57:42.921875000 +0200
1140 +++ bochs/bx_debug/dbg_main.cc 2006-01-25 23:39:08.937500000 +0200
1141 @@ -45,8 +45,18 @@ extern "C" {
1146 +static unsigned doit = 0;
1148 +#define SIM_NAME0 "bochs"
1149 +#ifndef SIM_NAME1_STR
1150 +#define SIM_NAME1_STR "sim1"
1152 +#define SIM_NAME(x) ((x == 0) ? SIM_NAME0 : SIM_NAME1_STR)
1154 // default CPU in the debugger. For commands like "dump_cpu" it will
1155 // use the default instead of always dumping all cpus.
1159 bx_param_bool_c *sim_running;
1160 @@ -58,9 +68,87 @@ static char tmp_buf_prev[512];
1161 static char *tmp_buf_ptr;
1162 static char *argv0 = NULL;
1164 +#if BX_NUM_SIMULATORS >= 2
1165 +#define BX_DBG_IO_JOURNAL_SIZE 1024
1166 +#define BX_DBG_UCMEM_JOURNAL_SIZE 1024
1167 +#define BX_DBG_ASYNC_JOURNAL_SIZE 1024
1168 +#define BX_DBG_MASTER_MODE 10
1169 +#define BX_DBG_SLAVE_MODE 11
1170 +// #define BX_DBG_DEFAULT_ICOUNT_QUANTUM 50
1171 +#define BX_DBG_DEFAULT_ICOUNT_QUANTUM 3 /* mch */
1173 +static unsigned bx_dbg_cosimulateN(bx_dbg_icount_t count);
1174 +static int bx_dbg_compare_sim_iaddr(void);
1175 +static bx_bool bx_dbg_compare_sim_cpu(void);
1176 +static bx_bool bx_dbg_compare_sim_memory(void);
1177 +static void bx_dbg_journal_a20_event(unsigned val);
1180 static FILE *debugger_log = NULL;
1183 +#if BX_NUM_SIMULATORS >= 2
1184 + // some fields used only for cosimulation
1185 + unsigned icount_quantum;
1186 + unsigned master_slave_mode;
1187 + unsigned master, slave;
1194 + } element[BX_DBG_IO_JOURNAL_SIZE];
1196 + unsigned head, tail;
1205 + } element[BX_DBG_UCMEM_JOURNAL_SIZE];
1207 + unsigned head, tail;
1210 +// need to handle DMA stuff in here...
1212 +#define BX_DBG_ASYNC_JOURNAL_NONE 0
1213 +#define BX_DBG_ASYNC_JOURNAL_A20 1
1214 +#define BX_DBG_ASYNC_JOURNAL_IAC 2
1215 +#define BX_DBG_ASYNC_JOURNAL_NMI 3
1216 +#define BX_DBG_ASYNC_JOURNAL_RESET 4
1218 + // Asynchronous events at the boundaries they are *taken* by the master simulator.
1219 + // These are replayed back to the slave at the same boundaries.
1222 + unsigned what; // A20, INTR, NMI, RESET, IAC, ...
1223 + bx_dbg_icount_t icount;
1227 + } a20, nmi, reset, iac;
1228 + // perhaps other more complex types here
1230 + } element[BX_DBG_ASYNC_JOURNAL_SIZE];
1232 + unsigned head, tail;
1239 + } compare_at_sync;
1241 + bx_bool fast_forward_mode;
1243 +#endif // #if BX_NUM_SIMULATORS >= 2
1245 // some fields used for single CPU debugger
1246 bx_bool auto_disassemble;
1247 unsigned disassemble_size;
1248 @@ -77,7 +165,19 @@ static struct {
1252 -#define BX_DBG_DEFAULT_ICOUNT_QUANTUM 3 /* mch */
1255 +// cosim commands for handling of comparison of simulator
1256 +// environments when both simulators have reached a common
1257 +// point (synchronized).
1259 +// cosim compare_at_sync iaddr (default is on)
1260 +// cosim compare_at_sync cpu (default is off)
1261 +// cosim compare_at_sync memory (default is off)
1262 +// cosim compare iaddr
1263 +// cosim compare cpu
1264 +// cosim compare memory
1269 @@ -97,8 +197,10 @@ static void bx_get_command(void);
1270 static void bx_dbg_print_guard_results();
1271 static void bx_dbg_breakpoint_changed(void);
1273 +bx_dbg_callback_t bx_dbg_callback[BX_NUM_SIMULATORS];
1274 bx_guard_t bx_guard;
1278 void bx_dbg_post_dma_reports(void);
1279 #define BX_BATCH_DMA_BUFSIZE 512
1280 @@ -138,8 +240,10 @@ void dbg_printf (const char *fmt, ...)
1282 int bx_dbg_main(int argc, char *argv[])
1284 - int i, bochs_argc=0;
1285 + int i, bochs_argc=0, sim1_argc=0, sim2_argc=0;
1286 char **bochs_argv = NULL;
1287 + char **sim1_argv = NULL;
1288 + char **sim2_argv = NULL;
1291 setbuf (stdout, NULL);
1292 @@ -148,11 +252,29 @@ int bx_dbg_main(int argc, char *argv[])
1293 bx_dbg_batch_dma.this_many = 1;
1294 bx_dbg_batch_dma.Qsize = 0;
1296 + // initialize callback functions, and guard environment
1297 + memset(bx_dbg_callback, 0, sizeof(bx_dbg_callback));
1298 memset(&bx_guard, 0, sizeof(bx_guard));
1299 bx_guard.async.irq = 1;
1300 bx_guard.async.dma = 1;
1302 memset(&bx_debugger, 0, sizeof(bx_debugger));
1303 +#if BX_NUM_SIMULATORS >= 2
1304 + bx_debugger.icount_quantum = BX_DBG_DEFAULT_ICOUNT_QUANTUM;
1305 + bx_debugger.IO_journal.size = 0;
1306 + bx_debugger.IO_journal.head = 0;
1307 + bx_debugger.IO_journal.tail = 0;
1308 + bx_debugger.UCmem_journal.size = 0;
1309 + bx_debugger.UCmem_journal.head = 0;
1310 + bx_debugger.UCmem_journal.tail = 0;
1311 + bx_debugger.async_journal.size = 0;
1312 + bx_debugger.async_journal.head = 0;
1313 + bx_debugger.async_journal.tail = 0;
1314 + bx_debugger.master = 0;
1315 + bx_debugger.slave = 1;
1316 + bx_debugger.compare_at_sync.iaddr = 1;
1317 + bx_debugger.fast_forward_mode = 0;
1319 bx_debugger.auto_disassemble = 1;
1320 bx_debugger.disassemble_size = 0;
1321 bx_debugger.default_display_format = 'x';
1322 @@ -166,7 +289,11 @@ int bx_dbg_main(int argc, char *argv[])
1323 bx_debug_rc_fname[0] = '\0';
1325 bochs_argv = (char **) &argv[0];
1326 + sim1_argv = bochs_argv; // start out with something reasonable
1327 + sim2_argv = bochs_argv; // start out with something reasonable
1332 // process "-rc pathname" option, if it exists
1334 @@ -182,6 +309,41 @@ int bx_dbg_main(int argc, char *argv[])
1335 bochs_argv = (char **) &argv[2];
1338 + // process options to bochs framework
1339 + for (; i<argc; i++) {
1340 + if (strcmp(argv[i], "-sim1") == 0) {
1343 + else if (strcmp(argv[i], "-sim2") == 0) {
1349 + if (i<argc) { // more args to process
1350 + // process options to each CPU simulator
1351 + if (strcmp(argv[i], "-sim1") == 0) {
1353 + sim1_argv = (char **) &argv[i];
1355 + for (; i<argc; i++) {
1356 + if (strcmp(argv[i], "-sim2") == 0)
1357 + goto process_sim2;
1361 + else if (strcmp(argv[i], "-sim2") == 0) {
1363 + sim2_argv = (char **) &argv[i];
1365 + for (; i<argc; i++) {
1366 + if (strcmp(argv[i], "-sim1") == 0)
1367 + goto process_sim1;
1373 bx_infile_stack_index = 0;
1374 bx_infile_stack[0].fp = stdin;
1375 strncpy(bx_infile_stack[0].fname, argv[0], BX_MAX_PATH);
1376 @@ -215,13 +377,36 @@ int bx_dbg_main(int argc, char *argv[])
1377 memset(bx_disasm_ibuf, 0, sizeof(bx_disasm_ibuf));
1380 + BX_SIM1_INIT(&bx_dbg_callback[0], sim1_argc, sim1_argv);
1381 +#if BX_NUM_SIMULATORS >= 2
1382 + BX_SIM2_INIT(&bx_dbg_callback[1], sim2_argc, sim2_argv);
1385 // parse any remaining args in the usual way
1386 bx_parse_cmdline (1, bochs_argc, bochs_argv);
1388 // initialize hardware
1391 - // Moved from main.cc
1392 +#if BX_NUM_SIMULATORS >= 2
1393 + bx_debugger.compare_at_sync.cpu = 0;
1394 + bx_debugger.compare_at_sync.memory = 0;
1397 + // call init routines for each CPU+mem simulator
1398 + // initialize for SMP. one memory, multiple processors.
1400 +#if BX_NUM_SIMULATORS > 1
1401 +#error cosimulation not supported until SMP stuff settles
1402 + BX_MEM(1) = new BX_MEM_C ();
1403 + BX_CPU(1) = new BX_CPU_C (BX_MEM(1));
1404 + BX_CPU(1)->reset(BX_RESET_HARDWARE);
1405 + BX_MEM(1)->init_memory(bx_options.memory.Osize->get () * 1024*1024);
1406 + BX_MEM(1)->load_ROM(bx_options.rom.path->getptr (), bx_options.rom.address->get (), 1);
1407 + BX_MEM(1)->load_ROM(bx_options.vgarom.path->getptr (), 0xc0000, 2);
1410 + // (mch) Moved from main.cc
1412 DEV_reset_devices(BX_RESET_HARDWARE);
1413 bx_gui->init_signal_handlers ();
1414 @@ -524,11 +709,16 @@ void bx_debug_break ()
1416 void bx_dbg_exit(int code)
1418 - BX_DEBUG(("dbg: before exit" ));
1419 + BX_DEBUG(("dbg: before sim1_exit" ));
1420 for (int cpu=0; cpu < BX_SMP_PROCESSORS; cpu++) {
1421 if (BX_CPU(cpu)) BX_CPU(cpu)->atexit();
1424 +#if BX_NUM_SIMULATORS >= 2
1425 + dbg_printf("before sim2_exit\n");
1426 + if (BX_CPU(1)) BX_CPU(1)->atexit();
1432 @@ -570,6 +761,17 @@ void bx_dbg_trace_reg_off_command(void)
1433 void bx_dbg_ptime_command(void)
1435 dbg_printf("ptime: " FMT_LL "d\n", bx_pc_system.time_ticks());
1436 +#if BX_NUM_SIMULATORS >= 2
1438 +#if BX_DBG_ICOUNT_SIZE == 32
1439 + "Last synchronized icount was %lu\n",
1440 + (unsigned long) bx_debugger.last_sync_icount
1441 +#else // BX_DBG_ICOUNT_SIZE == 64
1442 + "Last synchronized icount was %Lu\n",
1443 + (unsigned long long) bx_debugger.last_sync_icount
1444 +#endif /* BX_DBG_ICOUNT_SIZE == 32 */
1446 +#endif /* BX_NUM_SIMULATORS >= 2 */
1449 int timebp_timer = -1;
1450 @@ -1041,6 +1243,14 @@ void bx_dbg_continue_command(void)
1454 +#if BX_NUM_SIMULATORS >= 2
1455 + bx_guard.interrupt_requested = 0;
1456 + bx_guard.special_unwind_stack = 0;
1458 + if ( !bx_dbg_cosimulateN(bx_debugger.icount_quantum) )
1462 bx_guard.icount = 0;
1463 // I must guard for ICOUNT or one CPU could run forever without giving
1464 // the others a chance.
1465 @@ -1115,6 +1325,7 @@ one_more:
1466 BX_TICKN(max_executed);
1467 #endif /* BX_SUPPORT_SMP */
1469 +#endif /* BX_NUM_SIMULATORS */
1471 sim_running->set (0);
1473 @@ -1141,6 +1352,11 @@ void bx_dbg_stepN_command(bx_dbg_icount_
1474 // is printed, we will return to config mode.
1475 SIM->set_display_mode (DISP_MODE_SIM);
1477 +#if BX_NUM_SIMULATORS >= 2
1478 + bx_guard.interrupt_requested = 0;
1479 + bx_guard.special_unwind_stack = 0;
1480 + bx_dbg_cosimulateN(count);
1483 bx_guard.guard_for |= BX_DBG_GUARD_ICOUNT; // looking for icount
1484 bx_guard.guard_for |= BX_DBG_GUARD_CTRL_C; // or Ctrl-C
1485 @@ -1159,6 +1375,7 @@ void bx_dbg_stepN_command(bx_dbg_icount_
1491 BX_INSTR_DEBUG_PROMPT();
1492 bx_dbg_print_guard_results();
1493 @@ -1822,7 +2039,7 @@ void dbg_printf_binary (char *format, Bi
1496 void bx_dbg_examine_command(char *command, char *format, bx_bool format_passed,
1497 - Bit32u addr, bx_bool addr_passed)
1498 + Bit32u addr, bx_bool addr_passed, int simulator)
1500 unsigned repeat_count, i;
1501 char ch, display_format, unit_size;
1502 @@ -1837,7 +2054,10 @@ void bx_dbg_examine_command(char *comman
1504 unsigned char databuf[8];
1506 - printf("[bochs]:\n");
1507 + if (simulator == 0)
1508 + printf("[%s]:\n", SIM_NAME0);
1510 + printf("[%s]:\n", SIM_NAME1_STR);
1512 // If command was the extended "xp" command, meaning eXamine Physical memory,
1513 // then flag memory address as physical, rather than linear.
1514 @@ -1934,6 +2154,10 @@ void bx_dbg_examine_command(char *comman
1515 bx_debugger.default_unit_size = unit_size;
1518 + //dbg_printf(" repeat count was %u\n", repeat_count);
1519 + //dbg_printf(" display_format = '%c'\n", display_format);
1520 + //dbg_printf(" unit_size = '%c'\n", unit_size);
1522 if ( (display_format == 'i') || (display_format == 's') ) {
1523 dbg_printf("error: dbg_examine: 'i' and 's' formats not supported.\n");
1525 @@ -1996,7 +2220,7 @@ void bx_dbg_examine_command(char *comman
1529 - BX_CPU(0)->dbg_xlate_linear2phy(addr, &paddr, &paddr_valid);
1530 + BX_CPU(simulator)->dbg_xlate_linear2phy(addr, &paddr, &paddr_valid);
1532 dbg_printf("error: examine memory: no tranlation for linear-to-phy mem available.\n");
1534 @@ -2006,7 +2230,7 @@ void bx_dbg_examine_command(char *comman
1535 paddr = addr; // address is already physical address
1538 - BX_MEM(0)->dbg_fetch_mem(paddr, data_size, databuf);
1539 + BX_MEM(simulator)->dbg_fetch_mem(paddr, data_size, databuf);
1540 //FIXME HanishKVC The char display for data to be properly integrated
1541 // so that repeat_count, columns, etc. can be set or used properly.
1542 // Also for data_size of 2 and 4 how to display the individual
1543 @@ -2564,6 +2788,42 @@ void bx_dbg_instrument_command(const cha
1547 +void bx_dbg_loader_command(char *path_quoted)
1551 + // skip beginning double quote
1552 + if (path_quoted[0] == '"')
1555 + // null out ending quote
1556 + len = strlen(path_quoted);
1557 + if (path_quoted[len - 1] == '"')
1558 + path_quoted[len - 1] = '\0';
1562 + bx_loader_misc_t loader_misc;
1563 + bx_dbg_callback[0].loader(path_quoted, &loader_misc);
1565 + dbg_printf("dr0: 0x%08x\n", loader_misc.dr0);
1566 + dbg_printf("dr1: 0x%08x\n", loader_misc.dr1);
1567 + dbg_printf("dr2: 0x%08x\n", loader_misc.dr2);
1568 + dbg_printf("dr3: 0x%08x\n", loader_misc.dr3);
1569 + dbg_printf("dr6: 0x%08x\n", loader_misc.dr6);
1570 + dbg_printf("dr7: 0x%08x\n", loader_misc.dr7);
1572 + bx_cpu.dr0 = loader_misc.dr0;
1573 + bx_cpu.dr1 = loader_misc.dr1;
1574 + bx_cpu.dr2 = loader_misc.dr2;
1575 + bx_cpu.dr3 = loader_misc.dr3;
1576 + bx_cpu.dr7 = loader_misc.dr7;
1579 + dbg_printf("Error: loader not implemented.\n");
1583 void bx_dbg_doit_command(unsigned n)
1585 // generic command to add temporary hacks to
1586 @@ -2584,10 +2844,24 @@ void bx_dbg_crc_command(Bit32u addr1, Bi
1589 if (!BX_MEM(0)->dbg_crc32(crc32, addr1, addr2, &crc1)) {
1590 - dbg_printf("could not CRC memory\n");
1591 + dbg_printf("sim0: could not CRC memory\n");
1594 +#if BX_NUM_SIMULATORS == 1
1595 dbg_printf("0x%lx\n", crc1);
1597 + if (!BX_MEM(1)->dbg_crc32(crc32, addr1, addr2, &crc2)) {
1598 + dbg_printf("sim1: could not CRC memory\n");
1601 + if (crc1 == crc2) {
1602 + dbg_printf("CRC same: 0x%x\n", (unsigned) crc1);
1605 + dbg_printf("CRC different: sim0=0x%x, sim1=0x%x\n",
1606 + (unsigned) crc1, (unsigned) crc2);
1611 void bx_dbg_info_dirty_command(void)
1612 @@ -2931,10 +3205,51 @@ void bx_dbg_info_vga()
1614 void bx_dbg_iac_report(unsigned vector, unsigned irq)
1616 +#if BX_NUM_SIMULATORS > 1
1617 + unsigned tail, master;
1620 +if (doit) dbg_printf("iac report: vector=%u\n", vector);
1622 if (bx_guard.report.irq) {
1623 dbg_printf("event icount=%u IRQ irq=%u vec=%x\n",
1624 (unsigned) BX_CPU(dbg_cpu)->guard_found.icount, irq, vector);
1627 +#if BX_NUM_SIMULATORS > 1
1628 + if (bx_debugger.master_slave_mode == BX_DBG_SLAVE_MODE ) {
1629 + dbg_printf("Error: iac_report: in slave mode.\n");
1633 + // Master simulator mode
1634 + if (bx_debugger.async_journal.size >= BX_DBG_ASYNC_JOURNAL_SIZE) {
1635 + dbg_printf("Error: iac: async journal full.\n");
1639 + if (bx_debugger.async_journal.size == 0) {
1640 + // start off point head & tail at same element
1641 + bx_debugger.async_journal.head = 0;
1642 + tail = bx_debugger.async_journal.tail = 0;
1645 + tail = bx_debugger.async_journal.tail + 1;
1647 + if (tail >= BX_DBG_ASYNC_JOURNAL_SIZE) {
1648 + dbg_printf("Error: iac_report: journal wrapped.\n");
1652 + master = bx_debugger.master;
1653 + bx_debugger.async_journal.element[tail].what = BX_DBG_ASYNC_JOURNAL_IAC;
1654 + bx_debugger.async_journal.element[tail].icount = bx_guard_found[master].icount;
1655 + bx_debugger.async_journal.element[tail].u.iac.val = vector;
1657 + if (bx_debugger.async_journal.size)
1658 + bx_debugger.async_journal.tail++;
1659 + bx_debugger.async_journal.size++;
1663 void bx_dbg_a20_report(unsigned val)
1664 @@ -2955,6 +3270,8 @@ void bx_dbg_io_report(Bit32u addr, unsig
1665 (op==BX_READ) ? "read" : "write",
1669 + // nothing else to do. bx_dbg_inp() and bx_dbg_outp() do the journaling.
1672 void bx_dbg_ucmem_report(Bit32u addr, unsigned size, unsigned op, Bit32u val)
1673 @@ -2967,6 +3284,8 @@ void bx_dbg_ucmem_report(Bit32u addr, un
1674 (op==BX_READ) ? "read" : "write",
1677 + // nothing else to do. bx_dbg_ucmem_read() and bx_dbg_ucmem_write()
1678 + // do the journaling.
1681 void bx_dbg_dma_report(Bit32u addr, unsigned len, unsigned what, Bit32u val)
1682 diff -uBbwNpr bochs-nocosim/bx_debug/debug.h bochs/bx_debug/debug.h
1683 --- bochs-nocosim/bx_debug/debug.h 2006-01-25 22:58:39.187500000 +0200
1684 +++ bochs/bx_debug/debug.h 2006-01-25 23:35:58.671875000 +0200
1690 +#include "loader_misc.h"
1691 +void bx_dbg_loader(char *path, bx_loader_misc_t *misc_ptr);
1694 #if BX_DBG_ICOUNT_SIZE == 32
1695 typedef Bit32u bx_dbg_icount_t;
1696 #elif BX_DBG_ICOUNT_SIZE == 64
1697 @@ -143,6 +148,12 @@ void bx_dbg_trace_reg_on_command(void);
1698 void bx_dbg_trace_reg_off_command(void);
1699 void bx_dbg_ptime_command(void);
1700 void bx_dbg_timebp_command(bx_bool absolute, Bit64u time);
1701 +void bx_dbg_diff_memory(void);
1702 +void bx_dbg_always_check(Bit32u page_start, bx_bool on);
1703 +void bx_dbg_sync_memory(bx_bool set);
1704 +void bx_dbg_sync_cpu(bx_bool set);
1705 +void bx_dbg_fast_forward(Bit32u num);
1706 +void bx_dbg_info_address(Bit32u seg_reg_num, Bit32u offset);
1707 #define MAX_CONCURRENT_BPS 5
1708 extern int timebp_timer;
1709 extern Bit64u timebp_queue[MAX_CONCURRENT_BPS];
1710 @@ -189,7 +200,7 @@ void bx_dbg_info_flags(void);
1711 void bx_dbg_info_linux_command(void);
1712 void bx_dbg_info_symbols_command(char *Symbol);
1713 void bx_dbg_examine_command(char *command, char *format, bx_bool format_passed,
1714 - Bit32u addr, bx_bool addr_passed);
1715 + Bit32u addr, bx_bool addr_passed, int simulator);
1716 void bx_dbg_setpmem_command(Bit32u addr, unsigned len, Bit32u val);
1717 void bx_dbg_set_symbol_command(char *symbol, Bit32u val);
1718 void bx_dbg_query_command(char *);
1719 @@ -198,10 +209,11 @@ void bx_dbg_dump_cpu_command(void);
1720 void bx_dbg_set_cpu_command(void);
1721 void bx_dbg_disassemble_command(const char *,bx_num_range);
1722 void bx_dbg_instrument_command(const char *);
1723 +void bx_dbg_loader_command(char *);
1724 void bx_dbg_doit_command(unsigned);
1725 void bx_dbg_crc_command(Bit32u addr1, Bit32u addr2);
1726 extern bx_bool watchpoint_continue;
1727 -void bx_dbg_linux_syscall (unsigned which_cpu);
1728 +void bx_dbg_linux_syscall (void);
1729 void bx_dbg_info_ne2k(int page, int reg);
1730 void bx_dbg_info_pic(void);
1731 void bx_dbg_info_vga(void);
1732 @@ -423,12 +437,71 @@ typedef struct {
1733 unsigned inhibit_mask;
1738 + // call back functions specific to each simulator
1739 + bx_bool (*setphymem)(Bit32u addr, unsigned len, Bit8u *buf);
1740 + bx_bool (*getphymem)(Bit32u addr, unsigned len, Bit8u *buf);
1741 + void (*xlate_linear2phy)(Bit32u linear, Bit32u *phy, bx_bool *valid);
1742 + bx_bool (*set_reg)(unsigned reg, Bit32u val);
1743 + Bit32u (*get_reg)(unsigned reg);
1744 + bx_bool (*get_sreg)(bx_dbg_sreg_t *sreg, unsigned sreg_no);
1745 + bx_bool (*set_cpu)(bx_dbg_cpu_t *cpu);
1746 + bx_bool (*get_cpu)(bx_dbg_cpu_t *cpu);
1747 + unsigned dirty_page_tbl_size;
1748 + unsigned char *dirty_page_tbl;
1749 + void (*atexit)(void);
1750 + unsigned (*query_pending)(void);
1751 + void (*execute)(void);
1752 + void (*take_irq)(void);
1753 + void (*take_dma)(void);
1754 + void (*reset_cpu)(unsigned source);
1755 + void (*init_mem)(int size_in_bytes);
1756 + void (*load_ROM)(const char *path, Bit32u romaddress, Bit8u type);
1758 + // for asynchronous environment handling
1759 + void (*set_A20)(unsigned val);
1760 + void (*set_NMI)(unsigned val);
1761 + void (*set_RESET)(unsigned val);
1762 + void (*set_INTR)(unsigned val);
1763 + void (*force_interrupt)(unsigned vector);
1765 +#if BX_INSTRUMENTATION
1766 + void (*instr_start)(void);
1767 + void (*instr_stop)(void);
1768 + void (*instr_reset)(void);
1769 + void (*instr_print)(void);
1772 + void (*loader)(char *path, bx_loader_misc_t *misc_ptr);
1774 + bx_bool (*crc32)(Bit32u (*f)(const Bit8u *buf, int len),
1775 + Bit32u addr1, Bit32u addr2, Bit32u *crc);
1776 +} bx_dbg_callback_t;
1778 +extern bx_dbg_callback_t bx_dbg_callback[BX_NUM_SIMULATORS];
1780 +void BX_SIM1_INIT(bx_dbg_callback_t *, int argc, char *argv[]);
1781 +#ifdef BX_SIM2_INIT
1782 +void BX_SIM2_INIT(bx_dbg_callback_t *, int argc, char *argv[]);
1786 void bx_dbg_dma_report(Bit32u addr, unsigned len, unsigned what, Bit32u val);
1787 void bx_dbg_iac_report(unsigned vector, unsigned irq);
1788 void bx_dbg_a20_report(unsigned val);
1789 void bx_dbg_io_report(Bit32u addr, unsigned size, unsigned op, Bit32u val);
1790 void bx_dbg_ucmem_report(Bit32u addr, unsigned size, unsigned op, Bit32u val);
1792 +Bit8u bx_dbg_ucmem_read(Bit32u addr);
1793 +void bx_dbg_ucmem_write(Bit32u addr, Bit8u value);
1794 +void bx_dbg_async_pin_request(unsigned what, bx_bool val);
1795 +void bx_dbg_async_pin_ack(unsigned what, bx_bool val);
1796 +Bit32u bx_dbg_inp(Bit16u addr, unsigned len);
1797 +void bx_dbg_outp(Bit16u addr, Bit32u value, unsigned len);
1798 +void bx_dbg_raise_HLDA(void);
1799 +Bit8u bx_dbg_IAC(void);
1800 +void bx_dbg_set_INTR(bx_bool b);
1801 void bx_dbg_disassemble_current(int which_cpu, int print_time);
1803 int bx_dbg_symbolic_output(void); /* BW */
1804 diff -uBbwNpr bochs-nocosim/bx_debug/lexer.l bochs/bx_debug/lexer.l
1805 --- bochs-nocosim/bx_debug/lexer.l 2006-01-25 23:07:59.828125000 +0200
1806 +++ bochs/bx_debug/lexer.l 2006-01-25 20:13:44.000000000 +0200
1807 @@ -92,6 +92,7 @@ start { bxlval.sval = strdup(b
1808 stop { bxlval.sval = strdup(bxtext); return(BX_TOKEN_STOP); }
1809 reset { bxlval.sval = strdup(bxtext); return(BX_TOKEN_RESET); }
1810 print { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PRINT); }
1811 +loader { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LOADER); }
1812 doit { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DOIT); }
1813 trace-on { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACEON); }
1814 trace-off { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACEOFF); }
1815 @@ -118,6 +119,12 @@ slist { bxlval.sval = strdup(b
1816 global { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GLOBAL); }
1817 where { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WHERE); }
1818 print-string { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PRINT_STRING); }
1819 +diff-memory { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DIFF_MEMORY); }
1820 +sync-memory { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SYNC_MEMORY); }
1821 +sync-cpu { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SYNC_CPU); }
1822 +fast-forward { bxlval.sval = strdup(bxtext); return(BX_TOKEN_FAST_FORWARD); }
1823 +phy2log { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PHY_2_LOG); }
1824 +addr-info { bxlval.sval = strdup(bxtext); return(BX_TOKEN_INFO_ADDRESS); }
1825 ne2k { bxlval.sval = strdup(bxtext); return(BX_TOKEN_NE2000); }
1826 ne2000 { bxlval.sval = strdup(bxtext); return(BX_TOKEN_NE2000); }
1827 page { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PAGE); }
1828 @@ -155,6 +162,7 @@ ds { bxlval.uval = BX_DBG_S
1829 fs { bxlval.uval = BX_DBG_SREG_FS; return(BX_TOKEN_FS); }
1830 gs { bxlval.uval = BX_DBG_SREG_GS; return(BX_TOKEN_GS); }
1831 flags|eflags { bxlval.uval = 0; return (BX_TOKEN_FLAGS); }
1832 +force-check { bxlval.sval = strdup(bxtext); return(BX_TOKEN_ALWAYS_CHECK); }
1833 h|help { bxlval.sval = strdup(bxtext); return(BX_TOKEN_HELP); }
1835 calc { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CALC); }
1836 diff -uBbwNpr bochs-nocosim/bx_debug/linux.cc bochs/bx_debug/linux.cc
1837 --- bochs-nocosim/bx_debug/linux.cc 2006-01-25 22:34:23.281250000 +0200
1838 +++ bochs/bx_debug/linux.cc 2006-01-24 20:21:22.000000000 +0200
1839 @@ -153,11 +153,11 @@ char *syscall_names_t::get_name (int n)
1841 syscall_names_t syscall_names;
1843 -void bx_dbg_linux_syscall (unsigned which_cpu)
1845 - Bit32u eax = BX_CPU(which_cpu)->get_reg32(BX_32BIT_REG_EAX);
1846 - char *name = syscall_names.get_name (eax);
1847 - fprintf (stderr, "linux system call %s (#%d)\n", name, eax);
1848 +void bx_dbg_linux_syscall () {
1850 + bx_dbg_callback[0].get_cpu(&cpu);
1851 + char *name = syscall_names.get_name (cpu.eax);
1852 + fprintf (stderr, "linux system call %s (#%d)\n", name, cpu.eax);
1855 #endif /* if BX_DEBUGGER */
1856 diff -uBbwNpr bochs-nocosim/bx_debug/loader_misc.h bochs/bx_debug/loader_misc.h
1857 --- bochs-nocosim/bx_debug/loader_misc.h 1970-01-01 02:00:00.000000000 +0200
1858 +++ bochs/bx_debug/loader_misc.h 2003-11-28 17:07:25.000000000 +0200
1860 +/////////////////////////////////////////////////////////////////////////
1861 +// $Id: patch.cosimulation,v 1.2 2006/01/25 22:30:07 sshwarts Exp $
1862 +/////////////////////////////////////////////////////////////////////////
1864 +// Copyright (C) 2001 MandrakeSoft S.A.
1866 +// MandrakeSoft S.A.
1867 +// 43, rue d'Aboukir
1868 +// 75002 Paris - France
1869 +// http://www.linux-mandrake.com/
1870 +// http://www.mandrakesoft.com/
1872 +// This library is free software; you can redistribute it and/or
1873 +// modify it under the terms of the GNU Lesser General Public
1874 +// License as published by the Free Software Foundation; either
1875 +// version 2 of the License, or (at your option) any later version.
1877 +// This library is distributed in the hope that it will be useful,
1878 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
1879 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1880 +// Lesser General Public License for more details.
1882 +// You should have received a copy of the GNU Lesser General Public
1883 +// License along with this library; if not, write to the Free Software
1884 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1887 + unsigned long dr0;
1888 + unsigned long dr1;
1889 + unsigned long dr2;
1890 + unsigned long dr3;
1891 + unsigned long dr6;
1892 + unsigned long dr7;
1893 + } bx_loader_misc_t;
1895 +extern bx_loader_misc_t *bx_loader_misc_ptr;
1896 diff -uBbwNpr bochs-nocosim/bx_debug/parser.y bochs/bx_debug/parser.y
1897 --- bochs-nocosim/bx_debug/parser.y 2006-01-25 22:41:46.546875000 +0200
1898 +++ bochs/bx_debug/parser.y 2006-01-25 20:13:44.000000000 +0200
1900 %token <sval> BX_TOKEN_STOP
1901 %token <sval> BX_TOKEN_RESET
1902 %token <sval> BX_TOKEN_PRINT
1903 +%token <sval> BX_TOKEN_LOADER
1904 %token <sval> BX_TOKEN_STRING
1905 %token <sval> BX_TOKEN_DOIT
1906 %token <sval> BX_TOKEN_CRC
1907 @@ -138,11 +139,18 @@
1908 %token <sval> BX_TOKEN_GLOBAL
1909 %token <sval> BX_TOKEN_WHERE
1910 %token <sval> BX_TOKEN_PRINT_STRING
1911 +%token <sval> BX_TOKEN_DIFF_MEMORY
1912 +%token <sval> BX_TOKEN_SYNC_MEMORY
1913 +%token <sval> BX_TOKEN_SYNC_CPU
1914 +%token <sval> BX_TOKEN_FAST_FORWARD
1915 +%token <sval> BX_TOKEN_PHY_2_LOG
1916 %token <uval> BX_TOKEN_NUMERIC
1917 %token <ulval> BX_TOKEN_LONG_NUMERIC
1918 +%token <sval> BX_TOKEN_INFO_ADDRESS
1919 %token <sval> BX_TOKEN_NE2000
1920 %token <sval> BX_TOKEN_PIC
1921 %token <sval> BX_TOKEN_PAGE
1922 +%token <sval> BX_TOKEN_ALWAYS_CHECK
1923 %token <sval> BX_TOKEN_TRACEREGON
1924 %token <sval> BX_TOKEN_TRACEREGOFF
1925 %token <sval> BX_TOKEN_HELP
1926 @@ -190,6 +198,7 @@ command:
1928 | disassemble_command
1929 | instrument_command
1934 @@ -205,6 +214,7 @@ command:
1937 | print_string_command
1939 | trace_reg_on_command
1940 | trace_reg_off_command
1942 @@ -215,6 +225,48 @@ command:
1947 + BX_TOKEN_DIFF_MEMORY '\n'
1949 + bx_dbg_diff_memory();
1952 + | BX_TOKEN_SYNC_MEMORY BX_TOKEN_ON '\n'
1953 + | BX_TOKEN_SYNC_MEMORY BX_TOKEN_OFF '\n'
1955 + bx_dbg_sync_memory($2);
1958 + | BX_TOKEN_SYNC_CPU BX_TOKEN_ON '\n'
1959 + | BX_TOKEN_SYNC_CPU BX_TOKEN_OFF '\n'
1961 + bx_dbg_sync_cpu($2);
1964 + | BX_TOKEN_FAST_FORWARD BX_TOKEN_NUMERIC '\n'
1967 + bx_dbg_fast_forward($2);
1969 + | BX_TOKEN_PHY_2_LOG BX_TOKEN_NUMERIC '\n'
1973 + | BX_TOKEN_INFO_ADDRESS BX_TOKEN_SEGREG ':' BX_TOKEN_NUMERIC '\n'
1976 + bx_dbg_info_address($2, $4);
1978 + | BX_TOKEN_ALWAYS_CHECK BX_TOKEN_NUMERIC BX_TOKEN_ON '\n'
1982 + | BX_TOKEN_ALWAYS_CHECK BX_TOKEN_NUMERIC BX_TOKEN_OFF '\n'
1991 @@ -695,22 +747,44 @@ quit_command:
1993 BX_TOKEN_EXAMINE BX_TOKEN_XFORMAT expression '\n'
1995 - bx_dbg_examine_command($1, $2,1, $3, 1);
1996 + bx_dbg_examine_command($1, $2,1, $3,1, 0);
1997 +#if BX_NUM_SIMULATORS >= 2
1998 + bx_dbg_examine_command($1, $2,1, $3,1, 1);
2002 | BX_TOKEN_EXAMINE BX_TOKEN_XFORMAT '\n'
2004 - bx_dbg_examine_command($1, $2,1, 0, 0);
2005 + bx_dbg_examine_command($1, $2,1, 0,0, 0);
2006 +#if BX_NUM_SIMULATORS >= 2
2007 + bx_dbg_examine_command($1, $2,1, 0,0, 1);
2011 | BX_TOKEN_EXAMINE expression '\n'
2013 - bx_dbg_examine_command($1, NULL,0, $2, 1);
2014 + //FIXME HanishKVC This method of hunting thro all the
2015 + // simulators may be better than using 2 calls if
2016 + // BX_NUM_SIMULATORS greater than or equal to 2 as
2017 + // done for other cases of BX_TOKEN_EXAMINE
2019 + for(iCurSim = 0; iCurSim < BX_NUM_SIMULATORS; iCurSim++)
2021 + bx_dbg_examine_command($1, NULL,0, $2,1, iCurSim);
2025 | BX_TOKEN_EXAMINE '\n'
2027 - bx_dbg_examine_command($1, NULL,0, 0, 0);
2028 + //FIXME HanishKVC This method of hunting thro all the
2029 + // simulators may be better than using 2 calls if
2030 + // BX_NUM_SIMULATORS greater than or equal to 2 as
2031 + // done for other cases of BX_TOKEN_EXAMINE
2033 + for(iCurSim = 0; iCurSim < BX_NUM_SIMULATORS; iCurSim++)
2035 + bx_dbg_examine_command($1, NULL,0, 0,0, iCurSim);
2040 @@ -791,6 +865,14 @@ instrument_command:
2045 + BX_TOKEN_LOADER BX_TOKEN_STRING '\n'
2047 + bx_dbg_loader_command($2);
2048 + free($1); free($2);
2053 BX_TOKEN_DOIT BX_TOKEN_NUMERIC '\n'
2055 diff -uBbwNpr bochs-nocosim/bx_debug/sim2.cc bochs/bx_debug/sim2.cc
2056 --- bochs-nocosim/bx_debug/sim2.cc 1970-01-01 02:00:00.000000000 +0200
2057 +++ bochs/bx_debug/sim2.cc 2005-04-10 20:03:16.000000000 +0200
2059 +/////////////////////////////////////////////////////////////////////////
2060 +// $Id: patch.cosimulation,v 1.2 2006/01/25 22:30:07 sshwarts Exp $
2061 +/////////////////////////////////////////////////////////////////////////
2063 +// Copyright (C) 2001 MandrakeSoft S.A.
2065 +// MandrakeSoft S.A.
2066 +// 43, rue d'Aboukir
2067 +// 75002 Paris - France
2068 +// http://www.linux-mandrake.com/
2069 +// http://www.mandrakesoft.com/
2071 +// This library is free software; you can redistribute it and/or
2072 +// modify it under the terms of the GNU Lesser General Public
2073 +// License as published by the Free Software Foundation; either
2074 +// version 2 of the License, or (at your option) any later version.
2076 +// This library is distributed in the hope that it will be useful,
2077 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
2078 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2079 +// Lesser General Public License for more details.
2081 +// You should have received a copy of the GNU Lesser General Public
2082 +// License along with this library; if not, write to the Free Software
2083 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2085 +/////////////////////////////////////////////////////////////////////////
2091 +// NOTE: This file contains only stubs for a second CPU simulator
2092 +// to demonstrate use with the bochs debugger. The goal is to
2093 +// be able to run multiple simulators in a co-simulation environment.
2094 +// Each simulator has it's own CPU and memory space. There is only
2095 +// one set of device models, managed by the debugger.
2098 +bx_bool sim2_set_mem(Bit32u addr, unsigned len, Bit8u *buf);
2099 +bx_bool sim2_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf);
2100 +void sim2_xlate_linear2phy(Bit32u linear, Bit32u *phy, bx_bool *valid);
2101 +bx_bool sim2_set_reg(unsigned reg, Bit32u val);
2102 +Bit32u sim2_get_reg(unsigned reg);
2103 +bx_bool sim2_set_cpu(bx_dbg_cpu_t *cpu);
2104 +bx_bool sim2_get_cpu(bx_dbg_cpu_t *cpu);
2105 +unsigned dirty_page_tbl_size;
2106 +unsigned char sim2_dirty_pages[(BX_MAX_DIRTY_PAGE_TABLE_MEGS * 1024 * 1024) / 4096];
2107 +void sim2_atexit(void);
2108 +unsigned sim2_query_pending(void);
2109 +void sim2_cpu_loop(void);
2110 +void sim2_take_irq(void);
2111 +void sim2_take_dma(void);
2112 +void sim2_reset_cpu(void);
2113 +void sim2_init_mem(int size_in_bytes);
2114 +void sim2_load_ROM(const char *path, Bit32u romaddress, Bit8u type);
2116 +void sim2_set_A20(unsigned val);
2117 +void sim2_set_NMI(unsigned val);
2118 +void sim2_set_RESET(unsigned val);
2119 +void sim2_set_INTR(unsigned val);
2120 +void sim2_force_interrupt(unsigned vector);
2122 +#if BX_INSTRUMENTATION
2123 +void sim2_instr_start(void);
2124 +void sim2_instr_stop(void);
2125 +void sim2_instr_reset(void);
2126 +void sim2_instr_print(void);
2129 +void sim2_loader(char *path);
2133 +#if BX_DBG_EXTENSIONS
2134 +// return 0 if command not handled by extensions, bochs will handle
2135 +// return 1 if command handled by extensions, bochs will ignore
2136 +int bx_dbg_extensions(char *command)
2139 + return(0); // no extensions for now
2144 +void sim2_init(bx_dbg_callback_t *callback, int argc, char *argv[])
2146 + callback->setphymem = sim2_set_mem;
2147 + callback->getphymem = sim2_fetch_mem;
2148 + callback->xlate_linear2phy = sim2_xlate_linear2phy;
2149 + callback->set_reg = sim2_set_reg;
2150 + callback->get_reg = sim2_get_reg;
2151 + callback->get_cpu = sim2_get_cpu;
2152 + callback->set_cpu = sim2_set_cpu;
2153 + callback->dirty_page_tbl_size = sizeof(sim2_dirty_pages);
2154 + callback->dirty_page_tbl = sim2_dirty_pages;
2155 + callback->atexit = sim2_atexit;
2156 + callback->query_pending = sim2_query_pending;
2157 + callback->execute = sim2_cpu_loop;
2158 + callback->take_irq = sim2_take_irq;
2159 + callback->take_dma = sim2_take_dma;
2160 + callback->reset_cpu = sim2_reset_cpu;
2161 + callback->init_mem = sim2_init_mem;
2162 + callback->load_ROM = sim2_load_ROM;
2164 + // You may set this to NULL and use values in bx_pc_system as per
2165 + // docs-html/cosimulation.html
2166 + callback->set_A20 = sim2_set_A20;
2168 + callback->set_NMI = sim2_set_NMI;
2169 + callback->set_RESET = sim2_set_RESET;
2170 + callback->set_INTR = sim2_set_INTR;
2171 + callback->force_interrupt = sim2_force_interrupt;
2173 +#if BX_INSTRUMENTATION
2174 + callback->instr_start = sim2_instr_start;
2175 + callback->instr_stop = sim2_instr_stop;
2176 + callback->instr_reset = sim2_instr_reset;
2177 + callback->instr_print = sim2_instr_print;
2180 + callback->loader = sim2_loader;
2184 +bx_bool sim2_set_mem(Bit32u addr, unsigned len, Bit8u *buf)
2189 +bx_bool sim2_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf)
2194 +void sim2_xlate_linear2phy(Bit32u linear, Bit32u *phy, bx_bool *valid) { }
2196 +bx_bool sim2_set_reg(unsigned reg, Bit32u val)
2201 +Bit32u sim2_get_reg(unsigned reg)
2206 +bx_bool sim2_set_cpu(bx_dbg_cpu_t *cpu)
2211 +bx_bool sim2_get_cpu(bx_dbg_cpu_t *cpu)
2216 +void sim2_atexit(void) { }
2218 +unsigned sim2_query_pending(void)
2223 +void sim2_cpu_loop(void) { }
2225 +void sim2_take_irq(void) { }
2227 +void sim2_take_dma(void) { }
2229 +void sim2_reset_cpu(void) { }
2231 +void sim2_init_mem(int size_in_bytes) { }
2233 +void sim2_load_ROM(const char *path, Bit32u romaddress, Bit8u type) { }
2235 +void sim2_set_A20(unsigned val) { }
2237 +void sim2_set_NMI(unsigned val) { }
2239 +void sim2_set_RESET(unsigned val) { }
2241 +void sim2_set_INTR(unsigned val) { }
2243 +void sim2_force_interrupt(unsigned vector) { }
2245 +#if BX_INSTRUMENTATION
2246 +void sim2_instr_start(void) { }
2248 +void sim2_instr_stop(void) { }
2250 +void sim2_instr_reset(void) { }
2252 +void sim2_instr_print(void) { }
2256 +void sim2_loader(char *path) { }
2258 diff -uBbwNpr bochs-nocosim/config.h.in bochs/config.h.in
2259 --- bochs-nocosim/config.h.in 2006-01-25 22:46:50.765625000 +0200
2260 +++ bochs/config.h.in 2006-01-22 14:31:15.000000000 +0200
2262 #define BX_SUPPORT_SMP 0
2263 #define BX_BOOTSTRAP_PROCESSOR 0
2265 -// Controls how many instances of BX_MEM_C are created. For
2266 +// controls how many instances of BX_MEM_C are created. For
2267 // SMP, use several processors with one shared memory space.
2268 +// For cosimulation, you could use two processors and two address
2270 #define BX_ADDRESS_SPACES 1
2272 #if BX_ADDRESS_SPACES != 1
2273 @@ -685,6 +687,14 @@ typedef
2275 #define BX_INSTRUMENTATION 0
2277 +#define BX_USE_LOADER 0
2279 +// for debugger, CPU simulator handle ID
2280 +// 0 is the default, for using only one CPU simulator
2281 +// 1 is for the 2nd CPU simulator
2282 +#define BX_SIM_ID 0
2283 +#define BX_NUM_SIMULATORS 1
2285 // limited i440FX PCI support
2286 #define BX_SUPPORT_PCI 0
2288 diff -uBbwNpr bochs-nocosim/configure.in bochs/configure.in
2289 --- bochs-nocosim/configure.in 2006-01-25 22:37:48.781250000 +0200
2290 +++ bochs/configure.in 2006-01-18 20:35:36.000000000 +0200
2291 @@ -1392,6 +1392,34 @@ AC_ARG_ENABLE(instrumentation,
2292 AC_SUBST(INSTRUMENT_DIR)
2293 AC_SUBST(INSTRUMENT_VAR)
2295 +AC_ARG_ENABLE(simid,
2296 + [ --enable-simid=0 or 1 CPU simulator ID if using more than one],
2297 + [if test "$enableval" = yes; then
2298 + AC_DEFINE(BX_SIM_ID, 0)
2299 + elif test "$enableval" = no; then
2300 + AC_DEFINE(BX_SIM_ID, 0)
2302 + AC_DEFINE_UNQUOTED(BX_SIM_ID, $enableval)
2305 + AC_DEFINE(BX_SIM_ID, 0)
2309 +AC_ARG_ENABLE(num-sim,
2310 + [ --enable-num-sim=1 or 2 number of CPU simulators],
2311 + [if test "$enableval" = yes; then
2312 + AC_DEFINE(BX_NUM_SIMULATORS, 1)
2313 + elif test "$enableval" = no; then
2314 + AC_DEFINE(BX_NUM_SIMULATORS, 1)
2316 + AC_DEFINE_UNQUOTED(BX_NUM_SIMULATORS, $enableval)
2319 + AC_DEFINE(BX_NUM_SIMULATORS, 1)
2323 dnl // serial mode 'socket' needs wsock32.dll in non-plugin mode
2324 if test "$bx_plugins" = 0; then
2326 diff -uBbwNpr bochs-nocosim/cpu/cpu.cc bochs/cpu/cpu.cc
2327 --- bochs-nocosim/cpu/cpu.cc 2006-01-25 22:49:53.500000000 +0200
2328 +++ bochs/cpu/cpu.cc 2006-01-24 21:07:45.000000000 +0200
2329 @@ -1004,6 +1004,17 @@ bx_bool BX_CPU_C::dbg_is_end_instr_bpoin
2333 +#if (BX_NUM_SIMULATORS >= 2)
2334 + // if async event pending, acknowlege them
2335 + if (bx_guard.async_changes_pending.which) {
2336 + if (bx_guard.async_changes_pending.which & BX_DBG_ASYNC_PENDING_A20)
2337 + bx_dbg_async_pin_ack(BX_DBG_ASYNC_PENDING_A20,
2338 + bx_guard.async_changes_pending.a20);
2339 + if (bx_guard.async_changes_pending.which) {
2340 + BX_PANIC(("decode: async pending unrecognized."));
2344 return(0); // no breakpoint
2347 diff -uBbwNpr bochs-nocosim/cpu/debugstuff.cc bochs/cpu/debugstuff.cc
2348 --- bochs-nocosim/cpu/debugstuff.cc 2006-01-25 22:42:58.750000000 +0200
2349 +++ bochs/cpu/debugstuff.cc 2006-01-25 20:13:44.000000000 +0200
2350 @@ -987,6 +987,70 @@ bx_bool BX_CPU_C::dbg_set_cpu(bx_dbg_cpu
2355 +# define BX_DBG_NULL_CALLBACK bx_dbg_null_callback0
2357 +# define BX_DBG_NULL_CALLBACK bx_dbg_null_callback1
2359 +void BX_DBG_NULL_CALLBACK(unsigned val)
2361 + // bochs uses the pc_system variables, so this function is
2362 + // a stub for notification by the debugger, that a change
2369 +bx_dbg_init_cpu_mem_env0(bx_dbg_callback_t *callback, int argc, char *argv[])
2371 +bx_dbg_init_cpu_mem_env1(bx_dbg_callback_t *callback, int argc, char *argv[])
2379 +#warning hardcoding BX_CPU_THIS_PTR mem[0] and cpu[0]
2381 + callback->setphymem = BX_MEM(0)->dbg_set_mem;
2382 + callback->getphymem = BX_MEM(0)->dbg_fetch_mem;
2383 + callback->xlate_linear2phy = BX_CPU(0)->dbg_xlate_linear2phy;
2384 + callback->set_reg = BX_CPU(0)->dbg_set_reg;
2385 + callback->get_reg = BX_CPU(0)->dbg_get_reg;
2386 + callback->get_sreg = BX_CPU(0)->dbg_get_sreg;
2387 + callback->get_cpu = BX_CPU(0)->dbg_get_cpu;
2388 + callback->set_cpu = BX_CPU(0)->dbg_set_cpu;
2389 + callback->dirty_page_tbl_size = sizeof(BX_MEM(0)->dbg_dirty_pages);
2390 + callback->dirty_page_tbl = BX_MEM(0)->dbg_dirty_pages;
2391 + callback->atexit = BX_CPU(0)->atexit;
2392 + callback->query_pending = BX_CPU(0)->dbg_query_pending;
2393 + callback->execute = BX_CPU(0)->cpu_loop;
2394 + callback->take_irq = BX_CPU(0)->dbg_take_irq;
2395 + callback->take_dma = BX_CPU(0)->dbg_take_dma;
2396 + callback->reset_cpu = BX_CPU(0)->reset;
2397 + callback->init_mem = BX_MEM(0)->init_memory;
2398 + callback->load_ROM = BX_MEM(0)->load_ROM;
2399 + callback->set_A20 = NULL;
2400 + callback->set_NMI = BX_DBG_NULL_CALLBACK;
2401 + callback->set_RESET = BX_DBG_NULL_CALLBACK;
2402 + callback->set_INTR = BX_CPU(0)->set_INTR;
2403 + callback->force_interrupt = BX_CPU(0)->dbg_force_interrupt;
2405 +#if BX_INSTRUMENTATION
2406 + callback->instr_start = bx_instr_start;
2407 + callback->instr_stop = bx_instr_stop;
2408 + callback->instr_reset = bx_instr_reset;
2409 + callback->instr_print = bx_instr_print;
2412 + callback->loader = bx_dbg_loader;
2414 + callback->crc32 = BX_MEM(0)->dbg_crc32;
2418 #endif // #if BX_DEBUGGER
2420 void BX_CPU_C::atexit(void)
2421 diff -uBbwNpr bochs-nocosim/cpu/exception.cc bochs/cpu/exception.cc
2422 --- bochs-nocosim/cpu/exception.cc 2006-01-25 22:34:50.328125000 +0200
2423 +++ bochs/cpu/exception.cc 2005-12-13 00:01:22.000000000 +0200
2424 @@ -769,7 +769,7 @@ void BX_CPU_C::interrupt(Bit8u vector, b
2425 BX_CPU_THIS_PTR show_flag |= Flag_intsig;
2427 if (bx_dbg.linux_syscall) {
2428 - if (vector == 0x80) bx_dbg_linux_syscall(BX_CPU_ID);
2429 + if (vector == 0x80) bx_dbg_linux_syscall ();
2433 diff -uBbwNpr bochs-nocosim/cpu/init.cc bochs/cpu/init.cc
2434 --- bochs-nocosim/cpu/init.cc 2006-01-25 22:43:37.546875000 +0200
2435 +++ bochs/cpu/init.cc 2006-01-24 21:03:54.000000000 +0200
2436 @@ -942,7 +942,7 @@ void BX_CPU_C::sanity_checks(void)
2437 if (sizeof(Bit64u) != 8 || sizeof(Bit64s) != 8)
2438 BX_PANIC(("data type Bit64u or Bit64u is not of length 8 bytes!"));
2440 - BX_DEBUG(("#(%u)all sanity checks passed!", BX_CPU_ID));
2441 + BX_DEBUG(( "#(%u)all sanity checks passed!", BX_SIM_ID ));
2445 diff -uBbwNpr bochs-nocosim/cpu/lazy_flags.cc bochs/cpu/lazy_flags.cc
2446 --- bochs-nocosim/cpu/lazy_flags.cc 2006-01-25 22:43:53.859375000 +0200
2447 +++ bochs/cpu/lazy_flags.cc 2005-10-20 19:33:36.000000000 +0200
2450 #define LOG_THIS BX_CPU_THIS_PTR
2452 +#if BX_SIM_ID == 0 // only need to define once
2453 // This array defines a look-up table for the even parity-ness
2454 // of an 8bit quantity, for optimal assignment of the parity bit
2455 // in the EFLAGS register
2456 @@ -51,6 +52,7 @@ const bx_bool bx_parity_lookup[256] = {
2457 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
2458 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
2462 bx_bool BX_CPU_C::get_CFLazy(void)
2464 diff -uBbwNpr bochs-nocosim/load32bitOShack.cc bochs/load32bitOShack.cc
2465 --- bochs-nocosim/load32bitOShack.cc 2006-01-25 22:44:29.515625000 +0200
2466 +++ bochs/load32bitOShack.cc 2005-11-09 19:17:06.000000000 +0200
2467 @@ -309,8 +309,10 @@ bx_load_kernel_image(char *path, Bit32u
2471 - BX_INFO(("load_kernel_image: '%s', size=%u read into memory at %08x",
2472 - path, (unsigned) stat_buf.st_size, (unsigned) paddr));
2473 + BX_INFO(( "#(%u) load_kernel_image: '%s', size=%u read into memory at %08x",
2475 + (unsigned) stat_buf.st_size,
2476 + (unsigned) paddr ));
2480 diff -uBbwNpr bochs-nocosim/memory/misc_mem.cc bochs/memory/misc_mem.cc
2481 --- bochs-nocosim/memory/misc_mem.cc 2006-01-25 22:45:37.656250000 +0200
2482 +++ bochs/memory/misc_mem.cc 2006-01-24 21:03:55.000000000 +0200
2483 @@ -40,7 +40,7 @@ Bit32u BX_MEM_C::get_memory_in_k(void)
2484 BX_MEM_C::BX_MEM_C(void)
2487 - snprintf(mem, 6, "MEM0");
2488 + snprintf(mem, 6, "MEM%d", BX_SIM_ID);
2492 @@ -85,7 +85,7 @@ BX_MEM_C::~BX_MEM_C(void)
2493 memory_handlers = NULL;
2496 - BX_DEBUG(("Memory not freed as it wasn't allocated !"));
2497 + BX_DEBUG(("(%u) memory not freed as it wasn't allocated!", BX_SIM_ID));
2501 diff -uBbwNpr bochs-nocosim/pc_system.cc bochs/pc_system.cc
2502 --- bochs-nocosim/pc_system.cc 2006-01-25 22:50:16.625000000 +0200
2503 +++ bochs/pc_system.cc 2006-01-20 21:12:03.000000000 +0200
2504 @@ -104,12 +104,15 @@ void bx_pc_system_c::set_HRQ(bx_bool val
2505 BX_CPU(0)->async_event = 1;
2509 +#if (BX_NUM_SIMULATORS < 2)
2510 void bx_pc_system_c::set_INTR(bx_bool value)
2512 if (bx_dbg.interrupts)
2513 BX_INFO(("pc_system: Setting INTR=%d on bootstrap processor %d", (int)value, BX_BOOTSTRAP_PROCESSOR));
2514 BX_CPU(BX_BOOTSTRAP_PROCESSOR)->set_INTR(value);
2519 // Read from the IO memory address space