Fixed compilation error
[bochs-mirror.git] / patches / patch.cosimulation
blobc9b8a52504354011e540e6e32527e9c3d838752b
1 ----------------------------------------------------------------------
2 Patch name: Cosimulation support
3 Date: 25 Jan 2006
4 Status: Cosimulation not working yet.
6 Detailed description:
8 The cosimulation feature doesn't work since Bochs 2.0 release (or may be 
9 even earlier).
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 
20 strange way ...
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:
32   cvs diff -ubBwNp
34 Instructions:
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);
49  // needed.
50  //
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()
62 +#define BX_TICK1()
63 +#define BX_INTR                     bx_pc_system.INTR
64 +#define BX_SET_INTR(b)              bx_dbg_set_INTR(b)
65 +#if BX_SIM_ID == 0
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
70 +#else
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
75 +#endif
76 +#define BX_SET_ENABLE_A20(enabled)  bx_dbg_async_pin_request(BX_DBG_ASYNC_PENDING_A20, \
77 +                                      enabled)
78 +#define BX_GET_ENABLE_A20()         bx_pc_system.get_enable_a20()
79 +#error FIXME: cosim mode not fixed yet
81 +#else
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()
90 +#endif
92  #if BX_SUPPORT_A20
93  #  define A20ADDR(x)                ((x) & bx_pc_system.a20_mask)
94  #else
95 @@ -176,6 +210,21 @@ void bx_reset_options (void);
96  #if BX_DEBUGGER
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)
111 +#else
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
130  BX_OBJS = \
131    dbg_main.o \
132    symbols.o \
133 +  cosim.o \
134    linux.o \
136  BX_PARSER_OBJS = \
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
158 @@ -0,0 +1,979 @@
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
186 +#include "bochs.h"
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;
201 +  unsigned ret = 0;
202 +  bx_bool save_INTR;
203 +  bx_bool pre_A20, post_A20;
204 +  unsigned async_head;
205 +  bx_dbg_icount_t async_icount, curr_icount;
207 +  if (count == 0) {
208 +    dbg_printf ( "Error: cosimulateN: count=0\n");
209 +    bx_dbg_exit(1);
210 +  }
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
215 +one_time_slice:
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;
219 +  else
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) {
229 +    bail_out = 1;
230 +    dbg_printf ("ctrlc typed\n");
231 +  }
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;
242 +  slave_icount = 0;
243 +  if (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);
253 +    }
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)
258 +    bail_out = 1;
260 +  // Synchronize slave to master.  Account for Ctrl-C's typed during execution of
261 +  // slave.
262 +  bx_debugger.master_slave_mode = BX_DBG_SLAVE_MODE;
263 +  do {
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
274 +      }
275 +    else {
276 +      async_head   = 0; // keep compiler happy
277 +      async_icount = 0; // keep compiler happy
278 +      }
280 +    bx_guard_found[slave].guard_found = 0;
281 +    bx_guard_found[slave].icount = 0;
282 +    bx_guard.icount = curr_icount;
284 +    if (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;
292 +      } else {
293 +        BX_MEM(slave)->cpu_loop(-1);
294 +      }
295 +    }
296 +    slave_icount += bx_guard_found[slave].icount;
297 +    if (bx_guard_found[slave].guard_found & ~BX_DBG_GUARD_ICOUNT) {
298 +      bail_out = 1;
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))
303 +        break;
304 +    }
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");
309 +        bx_dbg_exit(1);
310 +      }
311 +      switch (bx_debugger.async_journal.element[async_head].what) {
312 +        case BX_DBG_ASYNC_JOURNAL_IAC:
313 +         if (!bx_debugger.fast_forward_mode) {
314 +            if (doit)
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);
320 +          }
321 +          break;
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);
328 +          break;
329 +        case BX_DBG_ASYNC_JOURNAL_NMI:
330 +        case BX_DBG_ASYNC_JOURNAL_RESET:
331 +        default:
332 +          dbg_printf ( "Error: cosimulateN: unimplemented async event.\n");
333 +      }
334 +      // async event processed, dequeue it
335 +      bx_debugger.async_journal.size--;
336 +      bx_debugger.async_journal.head++;
337 +    }
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.
345 +  int iaddr_res;
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)
349 +        bail_out = 1;
350 +    } else if (bx_debugger.compare_at_sync.cpu && bx_dbg_compare_sim_cpu())
351 +      bail_out = 1;
352 +    else if (bx_debugger.compare_at_sync.memory && bx_dbg_compare_sim_memory())
353 +      bail_out = 1;
354 +  }
356 +  if (bail_out) {
357 +#ifdef DEBUGGER_ERROR
358 +    extern void DEBUGGER_ERROR(void);
359 +    DEBUGGER_ERROR();
360 +#endif
362 +    ret = 0; // didn't complete, stopped
363 +  }
364 +  else {
365 +    count -= master_icount;
366 +    // last icount known to be in sync
367 +    bx_debugger.last_sync_icount += master_icount;
368 +    if (count)
369 +      goto one_time_slice;
370 +    ret = 1; // completed OK
371 +  }
373 +  bx_guard.guard_for &= ~BX_DBG_GUARD_ICOUNT;
374 +  return(ret);
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())
385 +      return 2;
386 +#endif
388 +    dbg_printf (
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
395 +#endif
396 +      );
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
402 +  }
403 +  return(0); // same
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);
417 +  bx_bool ret = 0;
418 +  bx_bool warn = 0;
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) \
423 +  do { \
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); \
426 +      ret = 1; \
427 +    } \
428 +  } while(0)
430 +#define TEST_REG_WARN(reg, reg_name, mask) \
431 +  do { \
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)); \
434 +      warn = 1; \
435 +    } \
436 +  } while(0)
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) \
454 +  do { \
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); \
457 +      ret = 1; \
458 +    } \
459 +  } while(0)
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);
473 +    ret = 1;
474 +  }
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);
478 +    ret = 1;
479 +  }
481 +  // drX ignored
482 +  // trX ignored
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);
493 +    ret = 1;
494 +  }
496 +  if (ret) {
497 +    dbg_printf (
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
504 +#endif
505 +      );
506 +  } else if (warn) {
507 +    dbg_printf (
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
514 +#endif
515 +      );
516 +#ifdef DEBUGGER_ERROR
517 +    extern void DEBUGGER_ERROR(void);
518 +    DEBUGGER_ERROR();
519 +#endif
520 +  }
522 +  return ret;
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;
531 +  }
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)
545 +  bx_bool ret = 0;
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]);
566 +          }
567 +        }
568 +        ret = 1;
569 +      }
570 +    }
571 +  }
573 +  if (ret) {
574 +    dbg_printf (
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
581 +#endif
582 +      );
583 +  }
585 +  clear_dirty_bits();
587 +  return ret;
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");
596 +    bx_dbg_exit(1);
597 +  }
599 +  // Master simulator mode
600 +  if (bx_debugger.async_journal.size >= BX_DBG_ASYNC_JOURNAL_SIZE) {
601 +    dbg_printf ( "Error: async journal full.\n");
602 +    bx_dbg_exit(1);
603 +  }
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;
609 +  }
610 +  else {
611 +    tail = bx_debugger.async_journal.tail + 1;
612 +  }
613 +  if (tail >= BX_DBG_ASYNC_JOURNAL_SIZE) {
614 +    dbg_printf ( "Error: a20_report: journal wrapped.\n");
615 +    bx_dbg_exit(0);
616 +  }
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)
630 +  Bit8u value;
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");
637 +        bx_dbg_exit(0);
638 +      }
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;
644 +      }
645 +      else {
646 +        tail = bx_debugger.UCmem_journal.tail + 1;
647 +      }
648 +      if (tail >= BX_DBG_UCMEM_JOURNAL_SIZE) {
649 +        dbg_printf ( "dbg_ucmem_read: journal wrapped.\n");
650 +        bx_dbg_exit(0);
651 +      }
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++;
663 +      if (doit)
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);
669 +      return(value);
670 +    } else {
671 +      value = DEV_vga_mem_read(addr);
672 +      return(value);
673 +    }
674 +  }
675 +  else {
676 +    if (bx_debugger.UCmem_journal.size == 0) {
677 +      dbg_printf ( "Error: ucmem_read: journal empty.\n");
678 +      return(0xff);
679 +    }
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))
686 +    {
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);
695 +      return(0xff);
696 +    }
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--;
700 +    return(value);
701 +  }
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");
712 +        bx_dbg_exit(0);
713 +      }
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;
719 +      }
720 +      else {
721 +        tail = bx_debugger.UCmem_journal.tail + 1;
722 +      }
723 +      if (tail >= BX_DBG_UCMEM_JOURNAL_SIZE) {
724 +        dbg_printf ( "dbg_ucmem_write: journal wrapped.\n");
725 +        bx_dbg_exit(0);
726 +      }
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);
738 +    } else {
739 +      DEV_vga_mem_write(addr, value);
740 +    }
741 +  }
742 +  else {
743 +    if (bx_debugger.UCmem_journal.size == 0) {
744 +      dbg_printf ( "Error: ucmem_write: journal empty.\n");
745 +      return;
746 +    }
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) )
753 +    {
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);
762 +      return;
763 +    }
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--;
767 +  }
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");
777 +    bx_dbg_exit(1);
778 +  }
780 +  switch (what) {
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;
785 +      return;
787 +    case BX_DBG_ASYNC_PENDING_RESET:
788 +    case BX_DBG_ASYNC_PENDING_NMI:
789 +    default:
790 +      dbg_printf ( "Error: set_async_pin: unhandled case.\n");
791 +      bx_dbg_exit(1);
792 +  }
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");
803 +    bx_dbg_exit(1);
804 +  }
806 +  switch (what) {
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);
815 +      return;
817 +    case BX_DBG_ASYNC_PENDING_RESET:
818 +    case BX_DBG_ASYNC_PENDING_NMI:
819 +    default:
820 +      dbg_printf ( "Error: set_async_pin: unhandled case.\n");
821 +      bx_dbg_exit(1);
822 +  }
825 +Bit32u bx_dbg_inp(Bit16u addr, unsigned len)
827 +  Bit32u value;
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");
834 +        bx_dbg_exit(0);
835 +      }
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;
841 +      }
842 +      else {
843 +        tail = bx_debugger.IO_journal.tail + 1;
844 +      }
845 +      if (tail >= BX_DBG_IO_JOURNAL_SIZE) {
846 +        dbg_printf ( "dbg_inp: journal wrapped.\n");
847 +        bx_dbg_exit(0);
848 +      }
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);
862 +      return(value);
863 +    } else {
864 +      value = bx_pc_system.inp(addr, len);
865 +      return(value);
866 +    }
867 +  }
868 +  else {
869 +    if (bx_debugger.IO_journal.size == 0) {
870 +      dbg_printf ( "Error: dbg_inp: journal empty.\n");
871 +      return(0xffffffff);
872 +    }
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);
887 +    }
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);
895 +    return(value);
896 +  }
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");
907 +        bx_dbg_exit(0);
908 +      }
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;
914 +      }
915 +      else {
916 +        tail = bx_debugger.IO_journal.tail + 1;
917 +      }
918 +      if (tail >= BX_DBG_IO_JOURNAL_SIZE) {
919 +        dbg_printf ( "dbg_outp: IO journal wrapped.\n");
920 +        bx_dbg_exit(0);
921 +      }
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);
931 +      if (doit)
932 +        dbg_printf ( "master: IO journal size now %u\n", bx_debugger.IO_journal.size);
933 +    } else {
934 +      bx_pc_system.outp(addr, value, len);
935 +    }
936 +  }
937 +  else {
938 +    if (bx_debugger.IO_journal.size == 0) {
939 +      dbg_printf ( "Error: dbg_outp: journal empty.\n");
940 +      return;
941 +    }
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);
956 +      return;
957 +    }
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--;
961 +    if (doit)
962 +      dbg_printf ( "slave: IO journal size now %u\n", bx_debugger.IO_journal.size);
963 +  }
966 +void bx_dbg_raise_HLDA(void)
968 +  dbg_printf ( "dbg_HLDA called\n");
969 +  bx_dbg_exit(0);
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
976 +  // the PIC code.
977 +  unsigned iac;
979 +  iac = BX_PIC_AIC ();
980 +  return(iac);
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");
987 +    bx_dbg_exit(1);
988 +  }
990 +  bx_pc_system.INTR = b;
991 +  BX_CPU(bx_debugger.master)->set_INTR(b);
994 +#endif
996 +void bx_dbg_diff_memory(void)
998 +#if BX_NUM_SIMULATORS < 2
999 +  printf("diff-memory supported only in cosimulation mode\n");
1000 +#else
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;
1004 +  }
1005 +  if (bx_dbg_compare_sim_memory())
1006 +    printf("[diff-memory] Diff detected\n");
1007 +  else
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");
1016 +#else
1017 +  bx_debugger.compare_at_sync.memory = set;
1018 +  printf("Memory sync %s\n", (set) ? "enabled" : "disabled");
1019 +#endif
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");
1026 +#else
1027 +  bx_debugger.compare_at_sync.cpu = set;
1028 +  printf("Register file sync %s\n", (set) ? "enabled" : "disabled");
1029 +#endif
1032 +void bx_dbg_fast_forward(Bit32u num)
1034 +#if BX_NUM_SIMULATORS < 2
1035 +  printf("fast-forward supported only in cosimulation mode\n");
1036 +#else
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))
1047 +      break;
1048 +  bx_debugger.fast_forward_mode = 0;
1049 +  // bx_debugger.icount_quantum = save_icount_quantum;
1051 +  DEV_vga_refresh();
1053 +  printf("Copying CPU...\n");
1054 +  bx_dbg_cpu_t cpu;
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);
1068 +    }
1069 +  }
1071 +  printf("Taking async events...\n");
1073 +  printf("Exiting fast-forward mode\n");
1074 +#endif
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");
1086 +#else
1087 +  for (int sim = 0; sim < 2; sim++) 
1088 +  {
1089 +    /* Find page table base address */
1090 +    bx_dbg_cpu_t regs;
1091 +    BX_CPU(sim)->dbg_get_cpu(&regs);
1092 +    Bit32u base = regs.cr3 & ~0xfff;
1094 +    Bit8u buf[4];
1095 +    Bit32u directory_addr = base + (offset >> 22) * 4;
1096 +    Bit32u directory;
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;
1100 +      Bit32u table;
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" : "-");
1122 +        } else {
1123 +          printf("[%s] Could not read from physical address %08x\n",
1124 +                 SIM_NAME(sim), directory_addr);
1125 +          return;
1126 +        }
1127 +      } else {
1128 +        printf("\n");
1129 +      }
1130 +    } else {
1131 +      printf("[%s] Could not read from physical address %08x\n",
1132 +             SIM_NAME(sim), directory_addr);
1133 +      return;
1134 +    }
1135 +  }
1136 +#endif
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" {
1143  #endif
1146 +static unsigned doit = 0;
1148 +#define SIM_NAME0 "bochs"
1149 +#ifndef SIM_NAME1_STR
1150 +#define SIM_NAME1_STR "sim1"
1151 +#endif
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.
1157  Bit32u dbg_cpu = 0;
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);
1178 +#endif
1180  static FILE *debugger_log = NULL;
1182  static struct {
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;
1188 +  struct {
1189 +    struct {
1190 +      Bit8u    op;
1191 +      Bit8u    len;
1192 +      Bit16u   addr;
1193 +      Bit32u   value;
1194 +    } element[BX_DBG_IO_JOURNAL_SIZE];
1195 +    unsigned size;
1196 +    unsigned head, tail;
1197 +  } IO_journal;
1199 +  struct {
1200 +    struct {
1201 +      Bit8u    op;
1202 +      Bit8u    len;
1203 +      Bit32u   addr;
1204 +      Bit32u   value;
1205 +    } element[BX_DBG_UCMEM_JOURNAL_SIZE];
1206 +    unsigned size;
1207 +    unsigned head, tail;
1208 +  } UCmem_journal;
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.
1220 +  struct {
1221 +    struct {
1222 +      unsigned        what; // A20, INTR, NMI, RESET, IAC, ...
1223 +      bx_dbg_icount_t icount;
1224 +      union {
1225 +        struct {
1226 +          unsigned val;
1227 +        } a20, nmi, reset, iac;
1228 +        // perhaps other more complex types here
1229 +      } u;
1230 +    } element[BX_DBG_ASYNC_JOURNAL_SIZE];
1231 +    unsigned size;
1232 +    unsigned head, tail;
1233 +  } async_journal;
1235 +  struct {
1236 +    bx_bool iaddr;
1237 +    bx_bool cpu;
1238 +    bx_bool memory;
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 {
1249  #endif
1250  } bx_debugger;
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
1267  typedef struct {
1268    FILE    *fp;
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;
1277  // DMA stuff
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;
1289    argc = 1;
1290    
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;
1318 +#endif
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
1328    bochs_argc = 1;
1329 +  sim1_argc = 1;
1330 +  sim2_argc = 1;
1332    // process "-rc pathname" option, if it exists
1333    i = 1;
1334 @@ -182,6 +309,41 @@ int bx_dbg_main(int argc, char *argv[])
1335      bochs_argv = (char **) &argv[2];
1336    }
1338 +  // process options to bochs framework
1339 +  for (; i<argc; i++) {
1340 +    if (strcmp(argv[i], "-sim1") == 0) {
1341 +      break;
1342 +    }
1343 +    else if (strcmp(argv[i], "-sim2") == 0) {
1344 +      break;
1345 +    }
1346 +    bochs_argc++;
1347 +  }
1349 +  if (i<argc) {  // more args to process
1350 +    // process options to each CPU simulator
1351 +    if (strcmp(argv[i], "-sim1") == 0) {
1352 +process_sim1:
1353 +      sim1_argv = (char **) &argv[i];
1354 +      i++;
1355 +      for (; i<argc; i++) {
1356 +        if (strcmp(argv[i], "-sim2") == 0)
1357 +          goto process_sim2;
1358 +        sim1_argc++;
1359 +      }
1360 +    }
1361 +    else if (strcmp(argv[i], "-sim2") == 0) {
1362 +process_sim2:
1363 +      sim2_argv = (char **) &argv[i];
1364 +      i++;
1365 +      for (; i<argc; i++) {
1366 +        if (strcmp(argv[i], "-sim1") == 0)
1367 +          goto process_sim1;
1368 +        sim2_argc++;
1369 +      }
1370 +    }
1371 +  }
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));
1378  #endif
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);
1383 +#endif
1385    // parse any remaining args in the usual way
1386    bx_parse_cmdline (1, bochs_argc, bochs_argv);
1388    // initialize hardware
1389    bx_init_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;
1395 +#endif
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);
1408 +#endif
1410 +  // (mch) Moved from main.cc
1411    DEV_init_devices();
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();
1422    }
1424 +#if BX_NUM_SIMULATORS >= 2
1425 +  dbg_printf("before sim2_exit\n");
1426 +  if (BX_CPU(1)) BX_CPU(1)->atexit();
1427 +#endif
1429    bx_atexit();
1430    BX_EXIT(code);
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
1437 +  dbg_printf (
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 */
1445 +  );
1446 +#endif /* BX_NUM_SIMULATORS >= 2 */
1449  int timebp_timer = -1;
1450 @@ -1041,6 +1243,14 @@ void bx_dbg_continue_command(void)
1452  one_more:
1454 +#if BX_NUM_SIMULATORS >= 2
1455 +  bx_guard.interrupt_requested = 0;
1456 +  bx_guard.special_unwind_stack = 0;
1457 +  while (1) {
1458 +    if ( !bx_dbg_cosimulateN(bx_debugger.icount_quantum) )
1459 +      break;
1460 +    }
1461 +#else
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 */
1468    }
1469 +#endif /* BX_NUM_SIMULATORS */
1471    sim_running->set (0);
1472    SIM->refresh_ci ();
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);
1481 +#else
1482    // single CPU
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_
1486      BX_TICK1 ();
1487  #endif
1488    }
1489 +#endif
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
1503    bx_bool is_linear;
1504    unsigned char databuf[8];
1506 -  printf("[bochs]:\n");
1507 +  if (simulator == 0)
1508 +    printf("[%s]:\n", SIM_NAME0);
1509 +  else
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;
1516    }
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");
1524      return;
1525 @@ -1996,7 +2220,7 @@ void bx_dbg_examine_command(char *comman
1526        dbg_printf(" ");
1528      if (is_linear) {
1529 -      BX_CPU(0)->dbg_xlate_linear2phy(addr, &paddr, &paddr_valid);
1530 +      BX_CPU(simulator)->dbg_xlate_linear2phy(addr, &paddr, &paddr_valid);
1531        if (!paddr_valid) {
1532          dbg_printf("error: examine memory: no tranlation for linear-to-phy mem available.\n");
1533          return;
1534 @@ -2006,7 +2230,7 @@ void bx_dbg_examine_command(char *comman
1535        paddr = addr;  // address is already physical address
1536      }
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
1544  #endif
1547 +void bx_dbg_loader_command(char *path_quoted)
1549 +  size_t len;
1551 +  // skip beginning double quote
1552 +  if (path_quoted[0] == '"')
1553 +    path_quoted++;
1555 +  // null out ending quote
1556 +  len = strlen(path_quoted);
1557 +  if (path_quoted[len - 1] == '"')
1558 +    path_quoted[len - 1] = '\0';
1560 +#if BX_USE_LOADER
1561 +  {
1562 +    bx_loader_misc_t loader_misc;
1563 +    bx_dbg_callback[0].loader(path_quoted, &loader_misc);
1564 +#if 0
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);
1571 +#endif
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;
1577 +  }
1578 +#else
1579 +  dbg_printf("Error: loader not implemented.\n");
1580 +#endif
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
1587    }
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");
1592      return;
1593    }
1594 +#if BX_NUM_SIMULATORS == 1
1595    dbg_printf("0x%lx\n", crc1);
1596 +#else
1597 +  if (!BX_MEM(1)->dbg_crc32(crc32, addr1, addr2, &crc2)) {
1598 +    dbg_printf("sim1: could not CRC memory\n");
1599 +    return;
1600 +  }
1601 +  if (crc1 == crc2) {
1602 +    dbg_printf("CRC same: 0x%x\n", (unsigned) crc1);
1603 +  }
1604 +  else {
1605 +    dbg_printf("CRC different: sim0=0x%x, sim1=0x%x\n",
1606 +            (unsigned) crc1, (unsigned) crc2);
1607 +  }
1608 +#endif
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;
1618 +#endif
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);
1625    }
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");
1630 +    bx_dbg_exit(1);
1631 +  }
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");
1636 +    bx_dbg_exit(1);
1637 +  }
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;
1643 +  }
1644 +  else {
1645 +    tail = bx_debugger.async_journal.tail + 1;
1646 +  }
1647 +  if (tail >= BX_DBG_ASYNC_JOURNAL_SIZE) {
1648 +    dbg_printf("Error: iac_report: journal wrapped.\n");
1649 +    bx_dbg_exit(0);
1650 +  }
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++;
1660 +#endif
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",
1666        (unsigned) val);
1667    }
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",
1675        (unsigned) val);
1676    }
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
1685 @@ -29,6 +29,11 @@
1686  #include "config.h"
1687  #include "osdep.h"
1689 +#if BX_USE_LOADER
1690 +#include "loader_misc.h"
1691 +void bx_dbg_loader(char *path, bx_loader_misc_t *misc_ptr);
1692 +#endif
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;
1734  } bx_dbg_cpu_t;
1737 +typedef struct {
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);
1770 +#endif
1771 +#if BX_USE_LOADER
1772 +  void    (*loader)(char *path, bx_loader_misc_t *misc_ptr);
1773 +#endif
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[]);
1783 +#endif
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); }
1834  \?              |
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 () {
1849 +  bx_dbg_cpu_t cpu;
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
1859 @@ -0,0 +1,36 @@
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
1886 +typedef struct {
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
1899 @@ -113,6 +113,7 @@
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:
1927      | set_cpu_command
1928      | disassemble_command
1929      | instrument_command
1930 +    | loader_command
1931      | doit_command
1932      | crc_command
1933      | trace_on_command
1934 @@ -205,6 +214,7 @@ command:
1935      | symbol_command
1936      | where_command
1937      | print_string_command
1938 +    | cosim_commands
1939      | trace_reg_on_command
1940      | trace_reg_off_command
1941      | help_command
1942 @@ -215,6 +225,48 @@ command:
1943        }
1944      ;
1946 +cosim_commands:
1947 +      BX_TOKEN_DIFF_MEMORY '\n'
1948 +        {
1949 +               bx_dbg_diff_memory();
1950 +               free($1);
1951 +       }
1952 +    | BX_TOKEN_SYNC_MEMORY BX_TOKEN_ON  '\n'
1953 +    | BX_TOKEN_SYNC_MEMORY BX_TOKEN_OFF '\n'
1954 +        {
1955 +               bx_dbg_sync_memory($2);
1956 +               free($1);
1957 +       }
1958 +    | BX_TOKEN_SYNC_CPU BX_TOKEN_ON  '\n'
1959 +    | BX_TOKEN_SYNC_CPU BX_TOKEN_OFF '\n'
1960 +        {
1961 +               bx_dbg_sync_cpu($2);
1962 +               free($1);
1963 +       }
1964 +    | BX_TOKEN_FAST_FORWARD BX_TOKEN_NUMERIC '\n'
1965 +        {
1966 +               free($1);
1967 +               bx_dbg_fast_forward($2);
1968 +       }
1969 +    | BX_TOKEN_PHY_2_LOG BX_TOKEN_NUMERIC '\n'
1970 +        {
1971 +               free($1);
1972 +       }
1973 +    | BX_TOKEN_INFO_ADDRESS BX_TOKEN_SEGREG ':' BX_TOKEN_NUMERIC '\n'
1974 +        {
1975 +               free($1);
1976 +               bx_dbg_info_address($2, $4);
1977 +        }
1978 +    | BX_TOKEN_ALWAYS_CHECK BX_TOKEN_NUMERIC BX_TOKEN_ON '\n'
1979 +        {
1980 +               free($1);
1981 +        }
1982 +    | BX_TOKEN_ALWAYS_CHECK BX_TOKEN_NUMERIC BX_TOKEN_OFF '\n'
1983 +        {
1984 +               free($1);
1985 +        }
1986 +    ;
1988  BX_TOKEN_SEGREG:
1989        BX_TOKEN_CS
1990      | BX_TOKEN_ES
1991 @@ -695,22 +747,44 @@ quit_command:
1992  examine_command:
1993        BX_TOKEN_EXAMINE BX_TOKEN_XFORMAT expression '\n'
1994          {
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);
1999 +#endif
2000          free($1); free($2);
2001          }
2002      | BX_TOKEN_EXAMINE BX_TOKEN_XFORMAT '\n'
2003          {
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);
2008 +#endif
2009          free($1); free($2);
2010          }
2011      | BX_TOKEN_EXAMINE expression '\n'
2012          {
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
2018 +        int iCurSim; 
2019 +        for(iCurSim = 0; iCurSim < BX_NUM_SIMULATORS; iCurSim++)
2020 +        {
2021 +          bx_dbg_examine_command($1, NULL,0, $2,1, iCurSim);
2022 +        }
2023          free($1);
2024          }
2025      | BX_TOKEN_EXAMINE '\n'
2026          {
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
2032 +        int iCurSim; 
2033 +        for(iCurSim = 0; iCurSim < BX_NUM_SIMULATORS; iCurSim++)
2034 +        {
2035 +          bx_dbg_examine_command($1, NULL,0, 0,0, iCurSim);
2036 +        }
2037          free($1);
2038          }
2039      ;
2040 @@ -791,6 +865,14 @@ instrument_command:
2041          }
2042      ;
2044 +loader_command:
2045 +      BX_TOKEN_LOADER BX_TOKEN_STRING '\n'
2046 +        {
2047 +        bx_dbg_loader_command($2);
2048 +        free($1); free($2);
2049 +        }
2050 +    ;
2052  doit_command:
2053        BX_TOKEN_DOIT BX_TOKEN_NUMERIC '\n'
2054          {
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
2058 @@ -0,0 +1,199 @@
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 +/////////////////////////////////////////////////////////////////////////
2088 +#include "bochs.h"
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);
2127 +#endif
2128 +#if BX_USE_LOADER
2129 +void    sim2_loader(char *path);
2130 +#endif
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)
2138 +  UNUSED(command);
2139 +  return(0); // no extensions for now
2141 +#endif
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;
2178 +#endif
2179 +#if BX_USE_LOADER
2180 +  callback->loader              = sim2_loader;
2181 +#endif
2184 +bx_bool sim2_set_mem(Bit32u addr, unsigned len, Bit8u *buf)
2186 +  return(0);
2189 +bx_bool sim2_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf)
2191 +  return(0);
2194 +void sim2_xlate_linear2phy(Bit32u linear, Bit32u *phy, bx_bool *valid) { }
2196 +bx_bool sim2_set_reg(unsigned reg, Bit32u val)
2198 +  return(0);
2201 +Bit32u sim2_get_reg(unsigned reg)
2203 +  return(0);
2206 +bx_bool sim2_set_cpu(bx_dbg_cpu_t *cpu)
2208 +  return(0);
2211 +bx_bool sim2_get_cpu(bx_dbg_cpu_t *cpu)
2213 +  return(0);
2216 +void sim2_atexit(void) { }
2218 +unsigned sim2_query_pending(void)
2220 +  return(0);
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) { }
2253 +#endif
2255 +#if BX_USE_LOADER
2256 +void sim2_loader(char *path) { }
2257 +#endif
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
2261 @@ -55,8 +55,10 @@
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
2269 +// spaces.
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)
2301 +   else
2302 +    AC_DEFINE_UNQUOTED(BX_SIM_ID, $enableval)
2303 +   fi],
2304 +  [
2305 +    AC_DEFINE(BX_SIM_ID, 0)
2306 +    ]
2307 +  )
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)
2315 +   else
2316 +    AC_DEFINE_UNQUOTED(BX_NUM_SIMULATORS, $enableval)
2317 +   fi],
2318 +  [
2319 +    AC_DEFINE(BX_NUM_SIMULATORS, 1)
2320 +    ]
2321 +  )
2323  dnl // serial mode 'socket' needs wsock32.dll in non-plugin mode
2324  if test "$bx_plugins" = 0; then
2325    case $target in
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
2330      }
2331    }
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."));
2341 +    }
2342 +  }
2343 +#endif
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
2351    return(1);
2354 +#if BX_SIM_ID == 0
2355 +#  define BX_DBG_NULL_CALLBACK bx_dbg_null_callback0
2356 +#else
2357 +#  define BX_DBG_NULL_CALLBACK bx_dbg_null_callback1
2358 +#endif
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
2363 +  // occurred.
2364 +  UNUSED(val);
2367 +  void
2368 +#if BX_SIM_ID == 0
2369 +bx_dbg_init_cpu_mem_env0(bx_dbg_callback_t *callback, int argc, char *argv[])
2370 +#else
2371 +bx_dbg_init_cpu_mem_env1(bx_dbg_callback_t *callback, int argc, char *argv[])
2372 +#endif
2374 +  UNUSED(argc);
2375 +  UNUSED(argv);
2377 +#if 0
2378 +#ifdef __GNUC__
2379 +#warning hardcoding BX_CPU_THIS_PTR mem[0] and cpu[0]
2380 +#endif
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;
2410 +#endif
2411 +#if BX_USE_LOADER
2412 +  callback->loader              = bx_dbg_loader;
2413 +#endif
2414 +  callback->crc32               = BX_MEM(0)->dbg_crc32;
2415 +#endif
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;
2426  #if BX_DEBUG_LINUX
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 ();
2430    }
2431  #endif
2432  #endif
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
2448 @@ -30,6 +30,7 @@
2449  #include "bochs.h"
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
2459  };
2460 +#endif
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 
2468      offset += ret;
2469      }
2470    close(fd);
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",
2474 +          BX_SIM_ID, path,
2475 +          (unsigned) stat_buf.st_size,
2476 +          (unsigned) paddr ));
2478    return page_size;
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)
2486    char mem[6];
2487 -  snprintf(mem, 6, "MEM0");
2488 +  snprintf(mem, 6, "MEM%d", BX_SIM_ID);
2489    put(mem);
2490    settype(MEMLOG);
2492 @@ -85,7 +85,7 @@ BX_MEM_C::~BX_MEM_C(void)
2493      memory_handlers = NULL;
2494    }
2495    else {
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));
2498    }
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);
2516 +#endif
2518  //
2519  // Read from the IO memory address space